SprinAOP的底层实现基于动态代理(JDK + CGLIB)。
AOP主要应⽤于⽇志记录,性能统计,安全控制,事务处理等⽅⾯,实现公共功能性的重复使⽤。
JDK动态代理
注:要求目标对象有接口实现
通过Proxy类的newProxyInstance()得到代理对象
Object proxy = Proxy.newProxyInstance(类加载器, 接口数组, InvocationHandler接口);
InvocationHandler接口中有invoke方法,代理过程在invoke方法中执行
当代理对象调用方法时,即会执行invoke方法
cglib 动态代理:
被代理⽬标对象可以不必实现接⼝,继承的⽅式实现。目标类不能使用final修饰。
需要在pom.xml引入cglib的依赖。
通过Enhancer的create方法,可以生成一个类,并设置该类的父类为目标类。
通过设置Enhancer对象的Callback方法,在callback方法中实现代理过程。
利用MethodInterceptor接口,该接口是Callback的子接口。
MethodInterceptor接口接口中,一个intercept方法,代理过程在intercept方法中执行
当代理对象调用方法时,即会执行intercept方法
AOP关键词
1. Joinpoint(连接点)被拦截到的每个点,spring中指被拦截到的每⼀个⽅法,spring aop⼀个连接点即代表⼀个⽅法的执⾏。
.2. Pointcut(切⼊点)对连接点进⾏拦截的定义(匹配规则定义 规定拦截哪些⽅法,对哪些⽅法进⾏处理),spring 有专⻔的表达式语⾔定义。
3. Advice(通知)拦截到每⼀个连接点即(每⼀个⽅法)后所要做的操作
1. 前置通知 (前置增强)@Before 执⾏⽅法前通知
2. 返回通知(返回增强) @AfterReturning ⽅法正常结束返回后的通知
3. 异常抛出通知(异常抛出增强)@AfterThrowing ⽅法抛出异常后的通知
4. 最终通知 @After ⽆论⽅法是否发⽣异常,均会执⾏该通知
5. 环绕通知 @Around包围⼀个连接点(join point)的通知,如⽅法调⽤。这是最强⼤的⼀种通知类型。 环绕通知可以在⽅法调⽤前后完成⾃定义的⾏为。它也会选择是否继续执⾏连接点或直接返回它们⾃⼰的返回值或抛出异常来结束执⾏。
4. Aspect(切⾯)切⼊点与通知的结合,决定了切⾯的定义,切⼊点定义了要拦截哪些类的哪些⽅法,通知则定义了拦截过⽅法后要做什么,切⾯则是横切关注点的抽象,与类相似,类是对物体特征的抽象,切⾯则是横切关注点抽象。
5. Target(⽬标对象)被代理的⽬标对象
.6. Weave(织⼊)将切⾯应⽤到⽬标对象并⽣成代理对象的这个过程即为织⼊
7. Introduction(引⼊)在不修改原有应⽤程序代码的情况下,在程序运⾏期为类动态添加⽅法或者字段的过程称为引⼊
AOP的实现
.1. 坐标依赖引⼊
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.9</version>
</dependency>
2. 添加spring.xml的配置
xmlns:aop="http://www.springframework.org/schema/aop" http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
3. 注解实现定义切⾯
@Aspect 声明当前类是⼀个切⾯
@Pointcut("匹配规则")声明当前方法是一个切⼊点
匹配规则
1. 执⾏任意公共⽅法: * execution(public *(..))
2. 执⾏任意的set⽅法 * execution(* set*(..))
3. 执⾏com.xxxx.service包下任意类的任意⽅法 * execution(* com.xxxx.service.*.*(..))
4. 执⾏com.xxxx.service 包 以及⼦包下任意类的任意⽅法 * execution(* com.xxxx.service..*.*(..))
表达式中的第⼀个* 代表的是⽅法的修饰范围 * 可选值:private、protected、public (* 表示所有范围)
4. 配置⽂件
<aop:aspectj-autoproxy/>