Spring AOP
注:本篇原自学习记录于周冠亚、黄文毅的
《Spring 5企业级开发实战》
。
AOP(Aspect Oriented Programming,面向切面编程)
动态代理,相对于
静态代理
而提出了的设计模式
Spring中,有两种动态代理:JDK、CGLIB
静态代理,一个代理类只能代理一个对象
JDK动态代理,动态生成,被代理对象必须实现接口 InvocationHandler
CGLIB动态代理,直接对Java类进行代理,需实现接口 MethodInterceptor
代理,给目标对象提供一个代理对象,通过代理对象去控制目标对象
怎么做到的呢,设计模式+反射
// JDK 动态代理为例
public interface Animal {
void eat();
}
public class Dog implements Animal {
@Override
public void eat() {
System.out.println("Dog需要吃骨头");
}
}
public class AnimalInvocationHandler implements InvocationHandler {
/**
* 被代理对象
*/
private Object target;
/**
* 绑定业务对象并返回一个代理类
* @param target
* @return
*/
public Object bind(Object target) {
this.target = target;
//通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
/**
* 接口方法
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result=null;
//方法执行前加一段逻辑
System.out.println("——————调用前处理——————");
//调用真正的业务方法
result=method.invoke(target, args);
//方法执行前加一段逻辑
System.out.println("——————调用后处理——————");
return result;
}
}
public class JDKDynamicProxyDemo {
public static void main(String[] args) {
//被代理对象
Dog dog = new Dog();
//动态代理类对象
AnimalInvocationHandler animalInvocationHandler = new AnimalInvocationHandler();
//代理对象
Animal proxy = (Animal) animalInvocationHandler.bind(dog);
proxy.eat();
}
}
以上就是Spring AOP的基本原理,只是Spring不需要开发人员自己维护代理类,其已帮开发人员生成了代理类。Spring AOP的实现是通过在程序运行时,根据具体的类对象和方法等信息动态地生成了一个代理类的class文件的字节码,再通过ClassLoader将代理类加载到内存中,最后通过生成的代理对象进行程序的方法调用。
-
AOP联盟
image.png
AOP是OOP的补充、完善
OOP:Object Oriented Programming
为啥会有AOP?
在OOP中,非核心、又通用的功能(日志、监控等)代码散落各处,重复且不利复用
将多个对象的公共模块分装成一个模块,形成一个Aspect
相关概念
- 横切关注点
方法拦截,增强原来方法
- 切面 Aspect
横切关注点的抽象
- 连接点 JoinPoint
程序执行中特定的点,Spring只支持方法类型的连接点,所有Spring AOP的连接点总表示一个方法的执行
- 切入点 Pointcut
切入点是匹配连接点的拦截规则,切入点表达式如何和连接点匹配是AOP的核心,Spring默认使用AspectJ切入点语法
- 通知 Advice
拦截特定的连接点之后的动作
- 目标对象 Target Object
需进行增强的对象
- 织入 Weaving
把切面作用到目标对象,然后产生一个代理对象的过程。
- 引入 Introduction
不需为类实现一个接口,就能使用接口中的方法。
AOP实现
JDK
- XML配置
- 注解
CGLIB
- XML配置
- 注解
Q:execution表达式
image.png
@Pointcut("execution(* com.test.aop.cglib.annotation.*.*(..))")
public void location() {}
返回类型是*
方法名是在那个包下的都可以
参数是任意的
基于Spring AOP的实战
image.png-
增强类型
- 前置
- 后置
- 环绕
- 异常抛出
- 引介
-
切入点
- 静态方法切入点StaticMethodMatcherPointcut
- 动态方法切入点DynamicMethodMatcherPointcut
- 注解切入点AnnotationMatchingPointcut
- 表达式切入点ExpressionPointcut
- 流程切入点ControlFlowPointcut
- 复合切入点ComposablePointcut
-
标准切入点TruePointcut
image.png
Spring集成AspectJ
AspectJ是一个面向切面的框架,其可以生成遵循Java字节码规范的Class文件。
Spring AOP和AscpectJ之间的关系:Spring使用了和AspectJ一样的注解,并使用AspectJ来做切入点解析和匹配。但是Spring AOP运行时并不依赖于AspectJ的编译器或者织入器等特性。
-
args/@args(入参)
-
annotation(特定注解)
-
execution
image.png -
target/@target
-
this
this不仅可以匹配Listener接口中定义的方法,而且还可以匹配FoodFactory中的方法
target仅仅匹配Listener中定义的方法。
- within/@within
Spring AOP的实现原理
image.pngSpring AOP的实现是通过创建目标对象的代理类,并对目标对象进行拦截来实现的
- ProxyFactoryBean类:功能是创建声明式的代理对象。
- ProxyFactory类:功能是创建编程式的代理对象。
- AspectJProxyFactory类:功能是创建基于AspectJ的代理对象。