0X01 前提条件
- 基于XML配置加载bean
- Spring V4.0.8.RELEASE
- bean为单例模式
- 基于JDK动态代理实现,Cglib暂且不表,其实两者大致流程差不多,只不过在生成具体代理对象的时候会有点差异
0X02 实现方法
要了解Spring AOP的实现原理需要将AnnotationAwareAspectJAutoProxyCreator,bean的创建和bean的方法调用三者联系起来。
AnnotationAwareAspectJAutoProxyCreator是bean的后置处理器,程序中开启了AOP功能的话,会将其注入到应用上下文中。AnnotationAwareAspectJAutoProxyCreator实现了接口SmartInstantiationAwareBeanPostProcessor,在bean工厂创建单例bean的过程中,一般会按以下顺序依次调用它的方法对bean加以处理:
我们主要关注的是postProcessBeforeInstantiation,postProcessAfterInitialization这两个方法有关,它们和代理对象的创建息息相关。
先来看postProcessBeforeInstantiation,它的主要作用是判断当前创建的bean是否需要增强,在判断的过程中它会收集bean工厂中实现了Advisor接口的增强器(那些正在创建的增强器它是不会获取的)以及将我们自定义的切面信息重新解析封装成一个个增强器,然后放入到缓存中。
而postProcessAfterInitialization方法就是真正创建代理对象的地方,它通过配置信息判断当前是使用jdk动态代理还是cglib代理来生成代理对象,spring提供了个默认的aop代理工厂DefaultAopProxyFactory来做这件事
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
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.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
生成了代理对象会将其与beanName相关联注入到应用上下文中,下面来讲讲实际的方法调用过程,可自行阅读JdkDynamicAopProxy的invoke方法,它才是真正实现那些通知调用的地方。首先会获取当前方法的方法拦截器
// Get the interception chain for this method.
//将advisor转换为methodInterceptor 即将增强器里的通知用方法拦截器重新封装下
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
这步其实是将增强器转换为方法拦截器,具体转换方法可查阅DefaultAdvisorAdapterRegistry类的getInterceptors方法
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
Advice advice = advisor.getAdvice();
//如果通知是MethodInterceptor实现类则直接放入集合中
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()]);
}
上述代码需要联系几个通知注解对应的通知实现类才好理解,以下代码片段摘自类ReflectiveAspectJAdvisorFactory的getAdvice方法
switch (aspectJAnnotation.getAnnotationType()) {
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, ajexp, aif);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, ajexp, aif);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
case AtAround:
springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif);
break;
获取到了方法拦截器后,下面就是正式进入相关方法调用:先是使用方法拦截器进行递归调用,最后一次递归调用才真正调用目标对象的方法
@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);
}
}
方法拦截器的调用是按照以下通知的顺序执行的
@Around>@Before>@After>@AfterReturn>@AfterThrowing