一、简介
AOP主要包含了通知、切点和连接点等术语,介绍如下:
通知(advice)
通知定义了切面是什么以及何时调用,何时调用包含以下几种
切点(PointCut)
通知定义了切面的什么和何时,切点定义了何处,切点的定义会匹配通知所要织入的一个或多个连接点,
我们通常使用明确的类的方法名称来指定这些切点,或是利用正则表达式定义匹配的类和方法名称来指定这些切点。
连接点(JoinPoint)
连接点是在应用执行过程中能够插入切面的一个点,这个点可以是调用方法时,抛出异常时,甚至是修改一个字段时,
切面代码可以利用这些连接点插入到应用的正常流程中,并添加新的行为,如日志、安全、事务、缓存等。
二、注解开发
声明一个切面,只需要在类名上添加@Aspect属性即可,具体的连接点,我们用@Pointcut和@Before、@After等标注。
在声明前 我们需要依赖配置pom
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.6.11</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.11</version> </dependency>
例子
package com.ganji.demo.service.aspect; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Service; /** * Created by admin on 2015/9/2. */ @Aspect @Service public class XmlAopDemoUserLog { // 配置切点 及要传的参数 @Pointcut("execution(* com.ganji.demo.service.user.UserService.GetDemoUser(..)) && args(id)") public void pointCut(int id) { } // 配置连接点 方法开始执行时通知 @Before("pointCut(id)") public void beforeLog(int id) { System.out.println("开始执行前置通知 日志记录:"+id); } // 方法执行完后通知 @After("pointCut(id)") public void afterLog(int id) { System.out.println("开始执行后置通知 日志记录:"+id); } // 执行成功后通知 @AfterReturning("pointCut(id)") public void afterReturningLog(int id) { System.out.println("方法成功执行后通知 日志记录:"+id); } // 抛出异常后通知 @AfterThrowing("pointCut(id)") public void afterThrowingLog(int id) { System.out.println("方法抛出异常后执行通知 日志记录"+id); } // 环绕通知 @Around("pointCut(id)") public Object aroundLog(ProceedingJoinPoint joinpoint,int id) { Object result = null; try { System.out.println("环绕通知开始 日志记录"+id); long start = System.currentTimeMillis(); //有返回参数 则需返回值 result = joinpoint.proceed(); long end = System.currentTimeMillis(); System.out.println("总共执行时长" + (end - start) + " 毫秒"); System.out.println("环绕通知结束 日志记录"); } catch (Throwable t) { System.out.println("出现错误"); } return result; } }
AOP切面中的同步问题
在WebLogAspect切面中,分别通过doBefore和doAfterReturning两个独立函数实现了切点头部和切点返回后执行的内容,
若我们想统计请求的处理时间,就需要在doBefore处记录时间,并在doAfterReturning处通过当前时间与开始处记录的时间计算
得到请求处理的消耗时间。
那么我们是否可以在WebLogAspect切面中定义一个成员变量来给doBefore和doAfterReturning一起访问呢?是否会有同步问题呢?
的确,直接在这里定义基本类型会有同步问题,所以我们可以引入ThreadLocal对象,像下面这样进行记录:
@Aspect @Component public class WebLogAspect { private Logger logger = Logger.getLogger(getClass()); ThreadLocal<Long> startTime = new ThreadLocal<>(); @Pointcut("execution(public * com.juzi.web..*.*(..))") public void webLog(){} @Before("webLog()") public void doBefore(JoinPoint joinPoint) throws Throwable { startTime.set(System.currentTimeMillis()); // 省略日志记录内容 } @AfterReturning(returning = "ret", pointcut = "webLog()") public void doAfterReturning(Object ret) throws Throwable { // 处理完请求,返回内容 logger.info("RESPONSE : " + ret); logger.info("SPEND TIME : " + (System.currentTimeMillis() - startTime.get())); } }
AOP切面的优先级
由于通过AOP实现,程序得到了很好的解耦,但是也会带来一些问题,比如:我们可能会对Web层做多个切面,校验用户,
校验头信息等等,这个时候经常会碰到切面的处理顺序问题。
所以,我们需要定义每个切面的优先级,我们需要@Order(i)注解来标识切面的优先级。i的值越小,优先级越高。
假设我们还有一个切面是CheckNameAspect用来校验name必须为didi,我们为其设置@Order(10),
而上文中WebLogAspect设置为@Order(5),所以WebLogAspect有更高的优先级,这个时候执行顺序是这样的:
在@Before中优先执行@Order(5)的内容,再执行@Order(10)的内容
在@After和@AfterReturning中优先执行@Order(10)的内容,再执行@Order(5)的内容
所以我们可以这样子总结:
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。
本文向大家介绍详解Spring Aop实例之AspectJ注解配置,包括了详解Spring Aop实例之AspectJ注解配置的使用技巧和注意事项,需要的朋友参考一下 上篇《Spring Aop实例之xml配置》中,讲解了xml配置方式,今天来说说AspectJ注解方式去配置spring aop。 依旧采用的jdk代理,接口和实现类代码请参考上篇博文。主要是将Aspect类分享一下: applic
本文向大家介绍Spring条件注解@Conditional示例详解,包括了Spring条件注解@Conditional示例详解的使用技巧和注意事项,需要的朋友参考一下 前言 @Conditional是Spring4新提供的注解,它的作用是根据某个条件创建特定的Bean,通过实现Condition接口,并重写matches接口来构造判断条件。总的来说,就是根据特定条件来控制Bean的创建行为,这样我
本文向大家介绍Spring @Conditional注解讲解及示例详解,包括了Spring @Conditional注解讲解及示例详解的使用技巧和注意事项,需要的朋友参考一下 前言: @Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件给容器注册bean。 @Conditional的定义: 从代码中可以看到,需要传入一个Class数组,并且需要继承Con
这里需要改的只有配置文件xml换成java文件: 测试类: 文件的位置为:
主要内容:Aop1.将业务逻辑组件和切面类都加入容器中,告诉Spring哪个是切面类@Aspect 2.在切面上的每一个方法加入通知注解,何时何地运行 @Pointcut,@Before,@After,@AfterReturning,@AfterThrowing,@Around 3.开启注解的Aop模式@EnableAspectJAutoProxy Aop 1.业务类 MathAop1.java 2.添加的业务类
本文向大家介绍spring aop注解配置代码实例,包括了spring aop注解配置代码实例的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了spring aop注解配置的具体代码,供大家参考,具体内容如下 Demo.java applicationContext.xml MyAdvice.java 以上所述是小编给大家介绍的spring aop注解配置详解整合,希望对大家有所帮助,