入口注解
首先我们来看关键注解EnableAspectJAutoProxy
该注解上有@Import(AspectJAutoProxyRegistrar.class)
该类的方法registerBeanDefinitions所做的事情是对需要被AOP起作用的bean生成新的代理bean
那么EnableAspectJAutoProxy是在哪里被使用的呢,看下面
代理方式
这里我们可以看到,springboot默认使用Cglib代理,若配置了spring.aop.proxy-target-class=false则使用Jdk动态代理,但bean没有接口时,则使用Cglib。
看下面这个例子
MyServiceImpl有接口,此时默认下MyService是Cglib
配置了spring.aop.proxy-target-class=false后是Jdk动态代理
我们再把接口去掉,配置依然是spring.aop.proxy-target-class=false
结果就使用了Cglib
准备切面
下面我们来沿着AspectJAutoProxyRegistrar 具体看一下内部实现
进入AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
这里会注册AnnotationAwareAspectJAutoProxyCreator为bean
来看一下AnnotationAwareAspectJAutoProxyCreator的继承结构
这是一个倒立的结构,可以看到它实现了接口InstantiationAwareBeanPostProcessor,该接口的方法postProcessBeforeInstantiation会在bean实例化之前执行(每个bean都会进来一次)
具体的实现在AbstractAutoProxyCreator中
这里最重要的是shouldSkip,该方法实际上做了很多提前准备数据的工作
可以看到这里把数据做了本地缓存,因为这些数据后面还要使用
而这里重要的是List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);这里面会把声明了@Aspect的类进行解析
到此postProcessBeforeInstantiation的关键流程就走完了
生成代理
接下来就需要对相关的bean创建aop代理bean了,再看一下继承结构
AnnotationAwareAspectJAutoProxyCreator还有个接口是BeanPostProcessor,而这个事情就是在postProcessAfterInitialization中完成的
具体的实现还是在AbstractAutoProxyCreator中
wrapIfNecessary如果允许就会生成代理
这里getProxy有Cglib和Jdk动态代理,而决定使用哪一种则是createAopProxy决定的
动态代理实现
先看JdkDynamicAopProxy的实现
很直观的就可以看到入参的InvocationHandler即是JdkDynamicAopProxy类自身
我们来看JdkDynamicAopProxy实现Object invoke(Object proxy, Method method, Object[] args)方法的关键部分
this.advised.getInterceptorsAndDynamicInterceptionAdvice方法将所有用于目标method的Advisors构建成Advice chain责任链
以下是各种Advice的封装
最后在retVal = invocation.proceed();时执行
CGLIB代理实现
再看CglibAopProxy的实现
我们来看getCallbacks的关键部分
这里的aopInterceptor是DynamicAdvisedInterceptor
可以看到这里使用了与JdkDynamicAopProxy 创建chain一样的方式
总结
以上就是Spring AOP的代理创建和运行原理
如果用一张图来表示结果
更多参考
CGLIB全网详细教程 - 简书 Cglib使用
AspectJ使用_赶路人儿的博客-CSDN博客_aspectj AspectJ使用