spring aop的源码解析内容比较多,分为三个部分:
1. 创建、初始化并注册AnnotationAwareAspectJAutoProxyCreator
参考:spring aop源码解析1: 创建、初始化并注册AnnotationAwareAspectJAutoProxyCreator
2. AnnotationAwareAspectJAutoProxyCreator拦截切点bean(join point)创建过程并生成proxy(在切点织入切面)的过程
参考:spring aop源码解析2: AnnotationAwareAspectJAutoProxyCreator拦截切点bean(join point)创建过程并生成proxy(在切点织入切面)的过程
3. 代理对象执行过程分析--构造拦截器链及触发拦截器链
参考:spring aop源码解析3: 代理对象执行过程分析--构造拦截器链及触发拦截器链
这一篇为第三篇。
接上一篇spring aop源码解析2: AnnotationAwareAspectJAutoProxyCreator拦截切点bean(join point)创建过程并生成proxy(在切点织入切面)的过程继续
6. 代理对象执行过程分析1--构造拦截器链
是如何实现先执行@Before,然后proceed,然后@After 然后@AfterReturning这样的顺序执行过程的呢?
容器中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存了详细信息(比如增强器,目标对象);
6.1 CglibAopProxy.intercept();拦截目标方法的执行
org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
private final AdvisedSupport advised;
public DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
}
}
通用AOP回调。 在目标是动态的或代理未冻结时使用。
接下来看其拦截逻辑
6.2 根据ProxyFactory对象获取将要执行的目标方法拦截器链;
可以获取到proxy中的target
target = getTarget();
if (target != null) {
targetClass = target.getClass();
}
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
org.springframework.aop.framework.DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice
6.2.1 List<Object> interceptorList保存所有增强器advice,有5个
一个默认的ExposeInvocationInterceptor 和 4个增强器;
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
6.2.2 遍历所有的增强器,将其转为Interceptor;
for (Advisor advisor : config.getAdvisors()) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
registry.getInterceptors(advisor);
6.2.3 将增强器转为List<MethodInterceptor>;
org.springframework.aop.framework.adapter.DefaultAdvisorAdapterRegistry#getInterceptors
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
}
如果是MethodInterceptor,直接加入到集合中
如果不是,使用AdvisorAdapter将增强器转为MethodInterceptor;
转换完成返回MethodInterceptor数组;
这个时候这个chain
拦截器链(每一个增强方法又被包装为方法拦截器,利用MethodInterceptor机制的intercept方法)
6.3 如果没有拦截器链,直接执行目标方法;
retVal = methodProxy.invoke(target, argsToUse);
6.4 如果有拦截器链,把需要执行的目标对象,目标方法,
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
拦截器链等信息传入创建一个 CglibMethodInvocation 对象,
并调用 Object retVal = mi.proceed();
7. 代理对象执行过程分析2--拦截器链触发过程
org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
@Override
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
7.1 如果没有拦截器执行执行目标方法,或者拦截器的索引和拦截器数组-1大小一样(指定到了最后一个拦截器)执行目标方法;
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
后面有一个++ this.currentInterceptorIndex
详细分析这个递归过程
7.1.1 第0号拦截器
第0号拦截器就是我们的第一个拦截器ExposeInvocationInterceptor
org.springframework.aop.interceptor.ExposeInvocationInterceptor#invoke
7.1.2 第1号拦截器
其又进入到
org.springframework.aop.framework.ReflectiveMethodInvocation#proceed中
拿到第1号拦截器AspectJAfterThrowing
org.springframework.aop.interceptor. AspectJAfterThrowingAdvice#invoke
7.1.3 第2号拦截器
其又进入到
org.springframework.aop.framework.ReflectiveMethodInvocation#proceed中
拿到第2号拦截器AfterReturningAdviceInterceptor
7.1.4 第3号拦截器
org.springframework.aop.interceptor. AfterReturningAdviceInterceptor#invoke
其又进入到
org.springframework.aop.framework.ReflectiveMethodInvocation#proceed中
拿到第3号拦截器AspectJAfterAdvice
org.springframework.aop.framework.adapter. AspectJAfterAdvice#invoke
7.1.5 第4号拦截器(最后的一个拦截器)
其又进入到
org.springframework.aop.framework.ReflectiveMethodInvocation#proceed中
拿到第4号拦截器MethodBeforeAdviceInterceptor
org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor#invoke
注意:这里的invoke方法有区别了
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}
其先调用前调通知方法
console中打印:
div运行。。。@Before:参数列表是:{[1, 0]}
由于已经执行到最后一个拦截器了
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
之后调用目标方法
console打印:
MathCalculator...div...
之后回到第3号拦截器AspectJAfterAdvice
console打印:
div结束。。。@After
之后回到第2号拦截器AfterReturningAdviceInterceptor
由于报错了,那么就直接将异常向上抛出
到第1号拦截器AspectJAfterThrowing
console打印:
div异常。。。异常信息:{java.lang.ArithmeticException: / by zero}
最后到第0号拦截器ExposeInvocationInterceptor
流程图:
线程堆栈情况
7.2 链式获取每一个拦截器,拦截器执行invoke方法,每一个拦截器等待下一个拦截器执行完成返回以后再来执行;
拦截器链的机制,保证增强方法与目标方法的执行顺序;
总结spring aop过程:
1. @EnableAspectJAutoProxy 开启AOP功能
2. @EnableAspectJAutoProxy 会给容器中注册一个组件
AnnotationAwareAspectJAutoProxyCreator
3. AnnotationAwareAspectJAutoProxyCreator是一个后置处理器;
4. finishBeanFactoryInitialization() 初始化剩下的单实例bean
4.1 创建业务逻辑组件MathCalculator和切面组件LogAspects
4.2 AnnotationAwareAspectJAutoProxyCreator这个后置处理器拦截组件的创建过程
4.3 组件创建完之后,根据切点表达式判断组件是否需要增强
把切面的增强方法,包装成增强器(Advisor);给业务逻辑组件创建一个代理对象(cglib/动态代理);
5. 执行目标方法:
5.1 代理对象执行目标方法
5.2 CglibAopProxy.intercept();
5.2.1 得到目标方法的拦截器链(增强器包装成拦截器MethodInterceptor)
5.2.2 利用拦截器的链式机制,依次进入每一个拦截器进行执行;
5.2.3 效果:
正常执行:前置通知-》目标方法-》后置通知-》返回通知
出现异常:前置通知-》目标方法-》后置通知-》异常通知
遗留的部分:在这三篇spring aop源代码解析中,忽略了一块内容,就是对aop xml的解析形成beanDefinition的部分,也没有讲如何对@Aspect,@Pointcut这些内容进行解析生成beanDefinition部分,这一块的设计在刘欣老师的spring aop课程中有简化实现。