AnnotationAwareAspectJAutoProxyCreator帮助我们基于注解实现AOP,它实现了BeanPostProcessor接口,那就从其实现的postProcessAfterInitialization方法(AbstractAutoProxyCreator#postProcessAfterInitialization)跟踪AOP是如何实现的。

跟踪源码来到AbstractAutoProxyCreator#wrapIfNecessary中的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

现在看一下具体每一步做了什么。

  • getAdvicesAndAdvisorsForBean

    • findCandidateAdvisors

首先使用BeanFactoryUtils#beanNamesForTypeIncludingAncestors(ListableBeanFactory, Class, boolean, boolean)获取所有的Advisor并使用BeanFactory#getBean(String, Class)实例化。

接着遍历所有的Object,通过AbstractAspectJAdvisorFactory#isAspect获取具有@Aspect注解的bean;再遍历bean,获取bean中不具有@Pointcut注解的方法,先按具有@Around@Before@After@AfterReturning@AfterThrowing排序,再按方法名排序;获取注解中表达式对应的AspectJExpressionPointcut;最后得到该bean相关的InstantiationModelAwarePointcutAdvisorImpl列表。使用BeanFactoryAspectJAdvisorsBuilder#advisorsCache保存beanName与其Advisor列表的对应关系。

    • findAdvisorsThatCanApply

上一步是获取所有切面,这一步是获取应用于当前bean的切面(AopUtils#canApply(Pointcut, Class, boolean))。

TODO

org.aspectj.util.PartialOrder#sort

  • createProxy

DefaultAdvisorAdapterRegistry#wrap将获取的切面都包装为Advisor实例,实例化ProxyFactory,由ProxyFactory#getProxy(ClassLoader)继续跟踪代码到JdkDynamicAopProxy#getProxy(ClassLoader),

1
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

返回代理之前会将Advised接口添加到proxiedInterfaces末尾。

JdkDynamicAopProxy实现了InvocationHandler,那下面就看一下它是如何实现invoke方法的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// Get the interception chain for this method.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;