Spring AOP如何实现简单的日志切面

技术Spring AOP如何实现简单的日志切面本篇文章给大家分享的是有关Spring AOP如何实现简单的日志切面,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看

本文是关于如何实现一个简单的Spring AOP日志部分。边肖觉得挺实用的,所以想分享给大家学习。希望大家看完这篇文章能有所收获。话不多说,让我们和边肖一起看看。

AOP

1.什么是 AOP ?

AOP被称为面向方面编程,它被翻译为面向方面编程。它是通过预编译和运行时动态代理实现核心业务逻辑以外的横切行为统一维护的技术。面向对象程序设计是面向对象程序设计的补充和扩展。AOP可以隔离业务逻辑的各个部分,从而减少模块之间的耦合,将影响多个类的公共行为封装成一个可重用的模块,从而提高程序的可重用性,提高开发效率,提高系统的可操作性和可维护性。

2.为什么要用 AOP ?

在实际的Web项目开发中,我们经常需要实现日志记录、性能统计、安全控制、事务处理、异常处理等功能。如果我们为每个级别的每个类独立编写这部分代码,那么随着时间的推移,代码将变得难以维护,所以我们将这些函数从业务逻辑代码中分离出来,并将其聚合起来进行维护,我们可以灵活地选择在哪里使用这些代码。

00-1010概念概念理解建议截取连接点后要执行的代码。通知分为五种类型:预通知、后通知、异常通知、最终通知和环绕通知,如日志记录、性能统计、安全控制、事务处理、异常处理等。解释何时做关节点的截取点。例如被拦截的方法、对类成员的访问以及异常处理程序块的执行等。您还可以嵌套到其他可以使用Joint PointSpring通知的地方。通过与方法相关的切入点截取连接点的定义指定了要通知哪个方法,并解释了在哪里剪切类的定义。包含切入点和建议的定义部分是通知和切入点的组合。切入点选择的目标对象,即要通知的对象;因为Spring AOP是通过代理模式实现的,所以这个对象始终是通过代理对象本身的业务逻辑进行编织,并将切面应用到目标对象的过程,从而创建AOP代理对象。编织可以在编译时、类加载时和运行时完成,而Spring通过在运行时完成截止点来定义将通知哪些连接点。Introduction可以在运行时为类动态添加方法和字段。Spring允许向所有目标对象引入新的接口。引言是介绍基于一个接口/类的新的接口增强功能AOP代理。Spring AOP可以使用JDK动态代理或者CGLIB代理,前者基于接口,后者基于类,使用代理将facets

3.AOP 的核心概念

Spring AOP

AOP应用到目标对象,这是Spring框架中的核心内容。在Spring中,AOP代理可以通过JDK动态代理或者CGLIB代理CglibAopProxy来实现。Spring中的AOP代理由Spring的IOC容器生成和管理,其依赖关系也由IOC容器管理。

1.简介

注意@Aspect将一个java类定义为切片类@Pointcut定义了一个切入点,它可以是一个正则表达式,比如下面例子中一个包下的所有函数。也可以是注释等。@在切入点开始处切入内容之前@在切入点结束处切入内容之后@在切入点之后返回处理逻辑之后返回内容@在切入点前后左右切入内容,自己控制什么时候执行切入点自己的内容@AfterThrowing用于在切入点部分抛出异常之后处理处理逻辑@Order(100)AOP段执行顺序,@Be。

fore 数值越小越先执行,@After 和 @AfterReturning 数值越大越先执行其中 @Before、@After、@AfterReturning、@Around、@AfterThrowing 都属于通知(Advice)。

利用 AOP 实现 Web 日志处理

1.构建项目

2.添加依赖

<dependencies>		<dependency>			<groupId>org.springframework.boot</groupId>			<artifactId>spring-boot-starter-web</artifactId>		</dependency>		<dependency>			<groupId>org.springframework.boot</groupId>			<artifactId>spring-boot-starter-test</artifactId>			<scope>test</scope>		</dependency>		<!-- 热部署模块 -->		<dependency>			<groupId>org.springframework.boot</groupId>			<artifactId>spring-boot-devtools</artifactId>			<optional>true</optional> <!-- 这个需要为 true 热部署才有效 -->		</dependency>		<!-- Spring AOP -->		<dependency>			<groupId>org.springframework.boot</groupId>			<artifactId>spring-boot-starter-aop</artifactId>		</dependency>	</dependencies>

3.Web 日志注解

@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface ControllerWebLog {	 String name();//所调用接口的名称     boolean intoDb() default false;//标识该条操作日志是否需要持久化存储}

4.实现切面逻辑

@Aspect@Component@Order(100)public class WebLogAspect {	private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);	private ThreadLocal<Map<String, Object>> threadLocal = new ThreadLocal<Map<String, Object>>();	/**	 * 横切点	 */	@Pointcut("execution(public * cn.zwqh.springboot.controller..*.*(..))")	public void webLog() {	}	/**	 * 接收请求,并记录数据	 * @param joinPoint	 * @param controllerWebLog	 */	@Before(value = "webLog()&& @annotation(controllerWebLog)")	public void doBefore(JoinPoint joinPoint, ControllerWebLog controllerWebLog) {		// 接收到请求		RequestAttributes ra = RequestContextHolder.getRequestAttributes();		ServletRequestAttributes sra = (ServletRequestAttributes) ra;		HttpServletRequest request = sra.getRequest();		// 记录请求内容,threadInfo存储所有内容		Map<String, Object> threadInfo = new HashMap<>();		logger.info("URL : " + request.getRequestURL());		threadInfo.put("url", request.getRequestURL());		logger.info("URI : " + request.getRequestURI());		threadInfo.put("uri", request.getRequestURI());		logger.info("HTTP_METHOD : " + request.getMethod());		threadInfo.put("httpMethod", request.getMethod());		logger.info("REMOTE_ADDR : " + request.getRemoteAddr());		threadInfo.put("ip", request.getRemoteAddr());		logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "."				+ joinPoint.getSignature().getName());		threadInfo.put("classMethod",				joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());		logger.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));		threadInfo.put("args", Arrays.toString(joinPoint.getArgs()));		logger.info("USER_AGENT"+request.getHeader("User-Agent"));		threadInfo.put("userAgent", request.getHeader("User-Agent"));		logger.info("执行方法:" + controllerWebLog.name());		threadInfo.put("methodName", controllerWebLog.name());		threadLocal.set(threadInfo);	}	/**	 * 执行成功后处理	 * @param controllerWebLog	 * @param ret	 * @throws Throwable	 */	@AfterReturning(value = "webLog()&& @annotation(controllerWebLog)", returning = "ret")	public void doAfterReturning(ControllerWebLog controllerWebLog, Object ret) throws Throwable {		Map<String, Object> threadInfo = threadLocal.get();		threadInfo.put("result", ret);		if (controllerWebLog.intoDb()) {			//插入数据库操作			//insertResult(threadInfo);		}		// 处理完请求,返回内容		logger.info("RESPONSE : " + ret);	}	/**	 * 获取执行时间	 * @param proceedingJoinPoint	 * @return	 * @throws Throwable	 */	@Around(value = "webLog()")	public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {		long startTime = System.currentTimeMillis();		Object ob = proceedingJoinPoint.proceed();		Map<String, Object> threadInfo = threadLocal.get();		Long takeTime = System.currentTimeMillis() - startTime;		threadInfo.put("takeTime", takeTime);		logger.info("耗时:" + takeTime);		threadLocal.set(threadInfo);		return ob;	}	/**	 * 异常处理	 * @param throwable	 */	@AfterThrowing(value = "webLog()", throwing = "throwable")	public void doAfterThrowing(Throwable throwable) {		RequestAttributes ra = RequestContextHolder.getRequestAttributes();		ServletRequestAttributes sra = (ServletRequestAttributes) ra;		HttpServletRequest request = sra.getRequest();		// 异常信息		logger.error("{}接口调用异常,异常信息{}", request.getRequestURI(), throwable);	}}

5.测试接口

@RestController@RequestMapping("/user")public class UserController {	@GetMapping("/getOne")	@ControllerWebLog(name = "查询", intoDb = true)	public String getOne(Long id, String name) {		return "1234";	}}

6.运行测试

浏览器请求:http://127.0.0.1:8080/user/getOne?id=1&name=zwqh ,可以看到后台日志输出: Spring AOP如何实现简单的日志切面

日志记录只是一个简单的示例,而 Spring AOP 的应用让整个系统变的更加有条不紊,在其他场景应用也很强大。 它帮助我们降低模块间耦合度,提高程序复用性,提高开发效率,提高系统可做性和可维护性。

以上就是Spring AOP如何实现简单的日志切面,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注行业资讯频道。

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/51145.html

(0)

相关推荐

  • 图书馆英语怎么写,怎样写图书馆的规则,英语)

    技术图书馆英语怎么写,怎样写图书馆的规则,英语)图书馆的规则.英语图书馆英语怎么写:1) Be quiet all time.2) Keep your voice low when you talk to others.

    生活 2021年10月21日
  • django orm中如何解决查询结果不区分大小写问题

    技术django orm中如何解决查询结果不区分大小写问题小编给大家分享一下django orm中如何解决查询结果不区分大小写问题,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有

    攻略 2021年11月23日
  • Java基础学习笔记

    技术Java基础学习笔记 Java基础学习笔记Java基础思维导图
    左键在“新标签页打开图片”可查看高清大图一、Java入门特性与优势
    高可用 高并发 高性能
    面向对象、多线程、简单性(去掉了内存分配、

    礼包 2021年12月1日
  • 前端浏览器的工作原理是什么

    技术前端浏览器的工作原理是什么这期内容当中小编将会给大家带来有关前端浏览器的工作原理是什么,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。浏览器架构在讲浏览器架构之前,先理解两个概念,进

    攻略 2021年12月3日
  • Go语言中什么是互斥锁

    技术Go语言中什么是互斥锁这篇文章将为大家详细讲解有关Go语言中什么是互斥锁,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1、互斥锁Mutex1.1 Mutex介绍Go

    攻略 2021年10月21日
  • cupro是什么面料,聚酯纤维面料是什么面料

    技术cupro是什么面料,聚酯纤维面料是什么面料聚酯纤维就是涤纶的一种叫法cupro是什么面料,商家用这个来混淆消费者的认识,因为涤纶是种低档廉价的纤维料嘛。涤纶具有许多优良的纺织性能和服用性能,用途广泛,可以纯纺织造,

    生活 2021年10月21日