Spring中AOP源码剖析
关键词
- aop的增强发生在后置处理器中(没有循环依赖)
- 最终增强是通过 递归调用 ,层层增强
一、环境准备
1.1 bean和接口
public class AopBean implements AopBeanInfo{
@Override
public void test() {
System.out.println("spring aop test... ...");
}
}
public interface AopBeanInfo {
public void test();
}
1.2 横切逻辑
/**
*
*/
public class LogUtils {
/**
* 前置通知
*/
public void beforeMethod() {
System.out.println("前置通知");
}
/**
* 最终通知
*/
public void alertMethod(){
System.out.println("最终通知");
}
/**
* 环绕通知
* @param pjp
* @return
* @throws Throwable
*/
public Object aroundMethod(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("环绕通知-pre");
Object proceed = pjp.proceed();
System.out.println("环绕通知-after");
return proceed;
}
/**
* 异常通知
*/
public void afterThrowingMethod(){
System.out.println("异常通知");
}
/**
* 后置通知
*/
public void afterReturning(){
System.out.println("后置通知");
}
}
1.3 配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
">
<!--循环依赖问题-->
<bean id="aopBean" class="com.dabing.source.aop.AopBean"></bean>
<!--aop配置-->
<!--横切逻辑-->
<bean id="logUtils" class="com.dabing.source.aop.LogUtils"></bean>
<aop:config>
<aop:aspect ref="logUtils">
<aop:before method="beforeMethod" pointcut="execution(public void com.dabing.source.aop.AopBean.test())"/>
<aop:after method="alertMethod" pointcut="execution(public void com.dabing.source.aop.AopBean.test())"/>
<aop:around method="aroundMethod" pointcut="execution(public void com.dabing.source.aop.AopBean.test())"/>
<aop:after-returning method="afterReturning" pointcut="execution(public void com.dabing.source.aop.AopBean.test())"/>
<aop:after-throwing method="afterThrowingMethod" pointcut="execution(public void com.dabing.source.aop.AopBean.test())"/>
</aop:aspect>
</aop:config>
</beans>
1.4 测试类:
/**
* 测试aop
*/
@Test
public void testAop(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext-aop.xml");
AopBeanInfo aopBean = applicationContext.getBean(AopBeanInfo.class);
aopBean.test();
}
1.5 测试结果:

二、源码剖析
2.1 实例化/增强链路构建阶段—源码剖析
在测试方法上添加断点,进行debug调试







在此处的断点设置过滤条件,只关注AopBean的创建流程

设置断点条件

放行


重点关注AopBean的后置处理器的处理流程,因为此案例的AOP增强是在Bean的后置处理器中进行的



在AspectJAwareAdvisorAutoProxyCreator中进行AOP增强




创建代理对象







2.2 执行阶段—源码剖析
1. 执行AopBean的test方法

2. 进入代理对象的invoke方法

3. 获取增强链集合(还有6个需要进行拦截增强的对象,其中5个和aop相关)

4. 递归调用proceed方法


5. 递归调用proceed方法,拦截增强对象(ExposeInvocationInterceptor),执行其invoke方法

此处进行了递归调用:在proceed方法中继续调用proceed方法

6. 递归调用proceed方法,拦截增强对象(MethodBeforeAdviceInterceptor),执行其invoke方法

在前置通知对象中,先执行前置逻辑,在进行后续递归操作






执行前置逻辑


继续进行后续递归操作

7. 递归调用proceed方法,拦截增强对象(AspectJAfterAdvice),执行其invoke方法

在最终通知对象中,先执行递归操作,在进行后续后置逻辑执行

先执行递归操作

8. 递归调用proceed方法,拦截增强对象(AspectJAroundAdvice),执行其invoke方法







执行具体的环绕通知逻辑-pre
继续递归调用


9. 递归调用proceed方法,拦截增强对象(AfterReturningAdviceInterceptor),执行其invoke方法

10. 递归调用proceed方法,拦截增强对象(AspectJAfterThrowingAdvice),执行其invoke方法

执行目标方法







目标方法执行完毕后


递归回后置通知,执行后置通知逻辑








一直往下执行
(执行方法略),直接展示回到环绕通知

一直往下执行
(执行方法略),直接展示回到最终通知

一直往下执行invoke方法(执行方法略),直接展示执行具体最终通知方法

至此,aop的执行过程执行完毕
总结
- aop的增强发生在后置处理器中(没有循环依赖)
- 最终增强是通过递归调用,层层增强
本文详细分析了Spring AOP中后置处理器的工作原理,揭示了如何在AopBean的test()方法执行后进行增强,并重点介绍了最终增强通过递归调用实现的过程。
2373

被折叠的 条评论
为什么被折叠?



