Spring AOP底层源码详解
作者:柠檬时间 时间:2022-03-12 02:00:26
目录
ProxyFactory的工作原理
JdkDynamicAopProxy创建代理对象过程
JdkDynamicAopProxy创建代理对象执行过程
ObjenesisCglibAopProxy创建代理对象过程
ObjenesisCglibAopProxy创建的代理对象执行过程
自动代理(autoproxy)功能
DefaultAdvisorAutoProxyCreator
@EnableAspectJAutoProxy
注解和源码对应关系
ProxyFactory的工作原理
ProxyFactory是一个代理对象生产工厂,在生成代理对象之前需要对代理工厂进行配置。ProxyFactory在生成代理对象之前需要决定到底是使用JDK * 还是CGLIB技术。
// config就是ProxyFactory对象
// optimize为true,或proxyTargetClass为true,或用户没有给ProxyFactory对象添加interface
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
// targetClass是接口,直接使用Jdk *
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 使用Cglib
return new ObjenesisCglibAopProxy(config);
}
else {
// 使用Jdk *
return new JdkDynamicAopProxy(config);
}
JdkDynamicAopProxy创建代理对象过程
获取生成代理对象所需要实现的接口集合
获取通过ProxyFactory.addInterface()所添加的接口,如果没有通过ProxyFactory.addInterface()添加接口,那么则看ProxyFactory。setTargetClass()所设置的targetClass是不是一个接口,把接口添加到结果集合中,同时把SpringProxy、Advised、DecoratingProxy这几个接口也添加到结果集合中去。
确定好要代理的集合之后,就利用Proxy.newProxyInstance()生成一个代理对象。
JdkDynamicAopProxy创建代理对象执行过程
如果通过ProxyFactory.setExposeProxy()把exposeProxy设置为true,那么则把代理对象设置到一个ThreadLocal(currentProxy)中去。
获取通过ProxyFactory所设置的target,如果设置的是targetClass,那么target将为null
根据当前所调用的方法对象寻找ProxyFactory中所添加的并匹配的Advisor,并且把Advisor封装为MethodInterceptor返回,得到MethodIntercepter链叫做chain
如果chain为空,则字节执行target对应的当前方法,如果target为null会报错
如果chain不为空,则会依次执行chain中的MethodInterceptor。如果当前MethodInterceptor是MethodBeforeAdviceInterceptor,那么先执行Advisor中所advice的before()方法,然后执行下一个MethodInterceptor.如果当前MethodInterceptor是AfterReturningAdviceInterceptor,那么先执行执行下一个MethodInterceptor。拿到返回值后,再执行Advisor中所advice的afterReturning()方法
ObjenesisCglibAopProxy创建代理对象过程
创建Enhancer
设置Enhancer的superClass为通过ProxyFactory.setTarget()所设置的对象的类
设置Enhancer的interfaces为通过ProxyFactory.addInterface()所添加的接口,以及SpringProxy、Advisor接口
设置Enhancer的Callbacks为DynamicAdvisedIntercepter
最后通过Enhancer创建一个代理对象
ObjenesisCglibAopProxy创建的代理对象执行过程
执行过程主要就看DynamicAdvisedInterceptor中的实现,执行逻辑和JdkDynamicAopProxy中是一样的。
自动代理(autoproxy)功能
“自动代理”表示只需要在Spring中添加某个Bean,这个Bean是一个BeanPostProcessor,那么Spring在每创建一个Bean时,都会经过这个BeanPost Processor的判断,去判断当前正在创建的这个Bean是不是需要进行AOP。
DefaultAdvisorAutoProxyCreator
AbstractAutoProxyCreator实现了SmartInstantiationAwareBeanPostProcessor接口,是一个BeanPostProcessor
在某个Bean实例化之前,查看该AbstractAutoProxyCreator中是不是设置了CustomTargetSource,如果设置了就查看当前Bean是不是需要创建一个TargetSource,如果需要就会创建一个TargetSource对象,然后进行AOP创建一个代理对象,并返回该代理对象
如果某个Bean出现了循环依赖,那么会利用getEarlyBeanReference()方法提前进行AOP
在某个Bean初始化之后,会调用wrapIfNecessary()方法进行AOP
在这个类中提供了一个抽象方法:getAdvicesAndAdvisorsForBean(),表示对于某个Bean匹配了哪些Advices和Advisors
AbstractAdvisorAutoProxyCreator继承了AbstractAutoProxyCreator,AbstractAdvisorAutoProxyCreator中实现了getAdvicesAndAdvisorsForBean()方法,实现逻辑为:
调用findEligibleAdvisors()
调用findCandidateAdvisors,得到所有Advisor类型的Bean。按当前正在进行Bean的生命周期的Bean进行过滤
@EnableAspectJAutoProxy
这个注解主要是添加了一个AnnotationAwareAspectJAutoProxyCreator类型的BeanDefinition。AspectJAwareAdvisorAutoProxyCreator继承了AbstractAdvisorAutoProxyCreator,重写了shouldSkip(Class<?> beanClass, String beanName)方法,表示某个bean需不需要进行AOP,在shouldSkip()方法中:
拿到所有的Advisor
遍历所有的Advisor,如果当前bean是AspectJPointcutAdvisor,那么则跳过
AnnotationAwareAspectJAutoProxyCreator继承了AspectJAwareAdvisorAutoProxyCreator,重写了findCandidateAdvisors()方法,它即可以找到Advisor类型的bean,也能把所有@Aspect注解标注的类扫描出来并生成Advisor
注解和源码对应关系
@Before对应的是AspectJMethodBeforeAdvice,直接实现MethodBeforeAdvice,在进行 * 时会把AspectJMethodBeforeAdvice转成MethodBeforeAdviceInterceptor,也就转变成了MethodBeforeAdviceInterceptor
先执行advice对应的方法
再执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
@After对应的是AspectJAfterAdvice,直接实现了MethodInterceptor
先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
再执行advice对应的方法
@Around对应的是AspectJAroundAdvice,直接实现了MethodInterceptor
直接执行advice对应的方法
@AfterThrowing对应的是AspectJAfterThrowingAdvice,直接实现了MethodInterceptor
先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
如果上面抛了Throwable,那么则会执行advice对应的方法
@AfterReturning对应的是AspectJAfterReturningAdvice,实现了AfterReturningAdvice,在进行 * 时会把AspectJAfterReturningAdvice转成AfterReturningAdviceInterceptor,也就转变成了MethodInterceptor
先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
执行上面的方法后得到最终的方法的返回值
再执行Advice对应的方法
来源:https://segmentfault.com/a/1190000039681753
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
SpringMVC数据响应详细介绍
![](https://img.aspxhome.com/file/2023/8/58568_0s.png)
fastjson转换对象实体@JsonProperty不生效问题及解决
![](https://img.aspxhome.com/file/2023/2/65312_0s.png)
Java shiro安全框架使用介绍
![](https://img.aspxhome.com/file/2023/3/69653_0s.png)
Java事务的个人理解小结
Struts2返回json格式数据代码实例
Android下拉列表spinner的实例代码
![](https://img.aspxhome.com/file/2023/2/86012_0s.jpg)
Mybatis下的SQL注入漏洞原理及防护方法解析
![](https://img.aspxhome.com/file/2023/2/63082_0s.png)
关于springboot集成swagger及knife4j的增强问题
![](https://img.aspxhome.com/file/2023/1/60271_0s.png)
mybatis-plus查询源码详解
![](https://img.aspxhome.com/file/2023/0/61300_0s.png)
Java中IO流解析及代码实例详解
基于Java文件输入输出流实现文件上传下载功能
![](https://img.aspxhome.com/file/2023/0/58170_0s.png)
Java基于链表实现栈的方法详解
![](https://img.aspxhome.com/file/2023/5/66045_0s.png)
基于JAVA文件中获取路径及WEB应用程序获取路径的方法
Java Spring开发环境搭建及简单入门示例教程
详解SpringBoot Start组件开发之记录接口日志信息
![](https://img.aspxhome.com/file/2023/5/57835_0s.jpg)
springboot整合JSR303校验功能实现代码
![](https://img.aspxhome.com/file/2023/8/72378_0s.jpg)
浅谈Java中复制数组的方式
Java毕业设计实战之图片展览馆管理系统的实现
![](https://img.aspxhome.com/file/2023/1/62521_0s.jpg)
iOS新浪微博、腾讯微博分享功能实例
![](https://img.aspxhome.com/file/2023/0/101960_0s.png)
深入理解Java并发编程之ThreadLocal
![](https://img.aspxhome.com/file/2023/8/59018_0s.jpg)