接上篇博客:Spring技术内幕3——Spring AOP原理(一)
Spring Aop最终转换成JdkDynamicAopProxy或者ObjenesisCglibAopProxy来作为入口对对象进行调用
JdkDynamicAopProxy的入口是invoke函数,ObjenesisCglibAopProxy的入口是DynamicAdvisedInterceptor的intercept方法。其实最终都是转化成ReflectiveMethodInvocation的proceed方法。
我们接下来看proceed方法的源码:
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); } }
根据之前的拦截器链进行相关的匹配,我们这里可以看到,它是遍历了所有的interceptorsAndDynamicMethodMatchers,那么interceptorsAndDynamicMethodMatchers这个是哪里来的呢?我们继续回头看。
我们在之前的配置中对ProxyFactoryBean配置了interceptorNames属性,我们在initializeAdvisorChain()初始化AdvisorChain链条的过程中,将interceptoeNames中相关的Bean对象作为Advisor注入到了
AdvisedSupport的advisors的List集合中,我们知道ProxyFactoryBean也是AdvisedSupport的子类
因此在:
@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); } }
这个方法中将ProxyBeanFactory已经注入了JdkDynamicAopProxy或者ObjenesisCglibAopProxy中,我们再回到CglibAopProxy或者JdkDynamicAopProxy这两个类中。
List
由此可以看出这边的拦截链就是调用的ProxyFactoryBean中的getInterceptorsAndDynamicInterceptionAdvice方法,而又因为ProxyFactoryBean继承于AdvisedSupport类,因此最终调用的是
DefaultAdvisorChainFactory中的getInterceptorsAndDynamicInterceptionAdvice方法。
public List
而config.getAdvisors().length则是ProxyFactoryBean中interceptorNames的配置的长度,我们继续往下看,可以看到这里使用了
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
作为一个注册器,真正的注册器则是这个DefaultAdvisorAdapterRegistry,我们可以看到Spring中使用了很多的涉及模式,把真正的实现和接口分离了开来。
/** * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters. */ public DefaultAdvisorAdapterRegistry() { registerAdvisorAdapter(new MethodBeforeAdviceAdapter()); registerAdvisorAdapter(new AfterReturningAdviceAdapter()); registerAdvisorAdapter(new ThrowsAdviceAdapter()); }@Override public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { Listinterceptors = new ArrayList (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()]); }
我们从名称基本可以看出这里注册了MethodBeforeAdvice、AfterReturningAdvice、ThrowAdvice这三个Advice的适配器,我们来看一个具体的适配器的相关过程
MethodBeforeAdviceAdapter中adapter.getTnterceptor调用的是:
@Override public boolean supportsAdvice(Advice advice) { return (advice instanceof MethodBeforeAdvice); } @Override public MethodInterceptor getInterceptor(Advisor advisor) { MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice(); return new MethodBeforeAdviceInterceptor(advice); }
返回的是MethodBeforeAdviceInterceptor的对象。
目前为止,我们返回了所有相关的Interceptor的集合,我们再来看ReflectiveMethodInvocation中的proceed方法:
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); }
调用的便是MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor、ThrowsAdviceInterceptor这单个Interceptor的相关的invoke方法了,分析这三个invoke方法,我们可以看见,在这里我们实现aop切面中的advice,对方法的前后实现了插入拦截。
例如:
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable { private MethodBeforeAdvice advice; /** * Create a new MethodBeforeAdviceInterceptor for the given advice. * @param advice the MethodBeforeAdvice to wrap */ public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; } @Override public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); return mi.proceed(); }}
总结一下:
Spring的Aop归根到底使用的还是jdk的反射。
主要流程是这样的:
ProxyFactoryBean(interceptorNames对象注入)——>getObject方法(初始化拦截器链)——>getSingletonInstance方法(判断target拦截对象是否为接口,使用不同的代理方式,并将ProxyFactoryBean对象注入相关代理接口)——>JdkDynamicAopProxy和ObjenesisCglibAopProxy接口调用相关的invoke方法和intercep方法作为代理的入口——>最终转化成ReflectiveMethodInvocation的proceed方法——>proceed方法中调用之前获取的拦截器链进行匹配拦截,对代理对象进行Advice切面增强。
补充拦截器链的相关过程
ProxyFactoryBean(interceptorNames对象注入)——>getObject方法——>initializeAdvisorChain——>addAdvisorOnChainCreation()——>AdvisedSupport的addAdvisor()——>DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice——>DefaultAdvisorAdapterRegistry的getInterceptors进行适配并返回相关拦截器——>调用连接器链的相关拦截器进行拦截