简单说说AOP的设计:
- 每个Bean都会被JDK或者Cglib代理。取决于是否有接口
- 每个Bean会有多个方法拦截器。拦截器分为两层,外层是由Spring内核控制流程,内层拦截器是用户设置,也就是AOP
- 当代理方法被调用时,先经过外层拦截器,外层拦截器根据方法的各种信息判断该方法应该执行哪些"内层拦截器"。内层拦截器的设计就是责任链的设计。
我们可以将AOP分成两部分来分析。第一:代理的创建;第二,代理的调用。
1、代理的创建(按步骤)
- 首先,需要创建代理工厂,代理工厂需要3个重要信息:拦截器数组,目标对象接口数组,目标对象接口数组,目标对象
- 创建代理工厂时,默认会在拦截器数组尾部再添加一个默认拦截器——用于最终的调用目标方法
- 当调用getProxy方法的时候,会根据接口数量大于0条件返回一个代理对象(JDK or Cglib)
- 注意: 创建代理对象时,同时会创建一个外层拦截器,这个拦截器就是Spring内核的拦截器。用于控制整个AOP的流程
2、代理的调用
- 当对代理对象进行调用时,就会触发外层拦截器
- 外层拦截器根据代理配置信息,创建内层拦截器链。创建的过程中,会根据表达式判断当前拦截的是否匹配这个拦截器。而这个拦截器链设计模式是职责链模式。
- 当整个链条执行到最后时,就会触发创建代理时那个尾部的默认拦截器,从而调用目标方法,最后返回。
AOP的两种代理方式
Spring提供了两种方式来生成代理对象:JDK动态代理和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。默认的策略是如果目标类是接口,则使用JDK动态代理技术,否则使用Cglib来生成代理。
JDK动态代理
JDK动态代理主要涉及java.lang.reflect包中的两个类:Proxy和InvocationHandler。
InvocationHandler是一个接口,通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编织在一起。Proxy利用InvocationHandler动态创建一个符合某一接口的实例,生成目标类的代理对象。
CGLib动态代理
CGLib全称Code Generation Library,是一个强大的高性能,高质量的代码生成库类,可以在运行期扩展Java类与实现Java接口,CGlib封装了asm,可以在运行期动态生成新的class。和 JDK 动态代理相比较:JDK 创建代理有一个限制,就是只能为接口创建代理实例,而对于没有通 过接口定义业务方法的类,则可以通过 CGLib 创建动态代理。