请简述下Spring AOP原理

89 阅读3分钟

简单说说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 创建动态代理。