目录
上一篇文章springAop原理之查找和原始bean关联的Advisor.已经分析了spring如何查找和判断Advisor是否和原始Bean关联,这里接着继续讲spring是如何根据这些Advisor创建代理bean及其代理bean方法具体执行过程
代理bean生成
AbstractAutoProxyCreator#wrapIfNecessary部分源码。可以看到将当前原始bean包装成SingletonTargetSource类型
// Create proxy if we have advice.
//获取bean有关的Advisor
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;
}
简化版createProxy方法,中间跳过,可以看到将包装后的bean和advisor添加到ProxyFatory中,也就是advised(ProxyFatory父类)中。下面都已advised代替ProxyFactory,继续往下
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
return proxyFactory.getProxy(getProxyClassLoader());
}
getProxy: createAopProxy()返回的就是基于基于JDK的JdkDynamicAopProxy
或基于CGLIB的ObjenesisCglibAopProxy,这里就不深入看了。
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
我们以JdkDynamicAopProxy为例分析getProxy方法。
记住在上面生成JdkDynamicAopProxy过程中,会将当前包含原始bean的包装类和advisor的advised赋值到JdkDynamicAopProxy属性AdvisedSupport advised中
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
最后一行代码就很熟悉了。我们知道jdk动态代理是需要一个InvocationHandler的实现类的,真正执行方法时是会执行InvocationHandler中的invoke方法。会发现JdkDynamicAopProxy自身就实现了该接口,所以后续代理对象方法的执行都是通过执行JdkDynamicAopProxy的invoke方法来触发的。
查找代理方法相关的Advisor
一开查找原始bean有关的advisor只是为了判断是否需要代理。但并不是说这些advisor会关联该bean的所有方法。以事务注解@Transactional为例来说,只有方法上由这个注解的(不考虑类上的)才会执行相应的切面逻辑,没有的则直接走原始bean的具体方法。所以这里就需要具体分析下JdkDynamicAopProxy中invoke方法。上面已经阐述了原理,这里直接分析源码。
简化版源码:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//1
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
//2
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
//3
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
return retVal;
}
}
- 代码中1处这句就是获取和方法相关的Advisor中的Advice,在spring中就是MethodInterceptor
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
我们知道advised中包含了原始bean的包装类和所有的advisor。该方法最终会调用DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法,该方法有些长,这里简单说下原理。
原理就是通过Advisor中的pointcut的ClassFilter和MethodMatcher 进行匹配,匹配结果为true的话,调用DefaultAdvisorAdapterRegistry的getInterceptors方法,将Advisor中的Advice包装成MethodInterceptor返回
所以最终上面的chain数组变量指向的就是和当前方法有关的所有Advice。
- 代码2处就是如果没有与当前方法相关的Advice,则直接反射执行原始bean的该方法
- 代码3处就是真正执行切面逻辑的。可以看到时委托给了ReflectiveMethodInvocation去执行,下面就具体分析下执行流程
代理方法执行流程
ReflectiveMethodInvocation采用责任链模式,依次执行每一个MethodInterceptor。
简化版的proceed方法。
interceptorsAndDynamicMethodMatchers就是传进来的Advice数组。
- 从数组第一个MethodInterceptor(MethodInterceptor代替Advice说明)开始执行其invoke方法。我们知道invoke方法是需要一个MethodInvocation类型的参数,而ReflectiveMethodInvocation就实现了该接口,所以将自身传了进去。
- MethodInvocation就是一种方法基本的链接点,所以MethodInterceptor的invoke方法最后必须执行MethodInvocation的proceed方法以执行具体的原始方法逻辑,或通过MethodInvocation的getMethod方法获取到原始方法并反射执行原始方法逻辑,
,不然原始的方法就不能够执行。这里只讨论proceed方法。所有的切面逻辑其实都是在执行proceed方法之前完成的。 - ReflectiveMethodInvocation的proceed方法又回到了第一步,接着获取第二个Advice来执行。如此循环就会执行完所有的advice。proceed方法开头的判断就是如果执行完了所有的advice,就执行invokeJoinpoint方法,也就时通过反射执行原始bean的原始方法。
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);
// 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);
}
这里有一点非常重要也很容易忽视。那就是最后通过反射执行原始方法的返回值并不是直接返给
//3
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
上面代码的 ,而是返给上一个MethodInterceptor的,第一个MethodInterceptor的invoke方法的返回值才是返给上述代码的。也就是说如果再不改变原始方法的返回值的情况下,原始的返回值会倒叙一层一层往上返回。
为啥要说这一点呢,因为很重要。比如以事务相关的TransactionInterceptor来说,它的invoke方法会调用父类TransactionAspectSupport的invokeWithinTransaction方法,下方为部分源码。正是通过此方法开启事务/提交事务/回滚事务。下方代码1处就可以获取到原始方法返回值。发生异常回滚,正常则提交事务。
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
//1
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
commitTransactionAfterReturning(txInfo);
return retVal;