Spring AOP(二) 原理
Spring AOP所使用的到的原理就是采取一种代理模式,spring AOP中提供了两种方式产生代理对象:jdk动态代理和CGLIB代理。这两者的优势和局限性在这里不做讨论。
一、代理对象的生成
Spring AOP模块中,一个主要的部分就是代理对象的生成,从中Spring AOP(一) 基本概念和例子我们可以知道,可以通过配置和调用Spring的ProxyFactoryBean来完成这个任务。当然Spring AOP中提供了多种方式来生成代理对象。下面给出主要的继承关系(并非全部继承关系)
- ProxyConfig:可以看成是一个数据基类,这个数据基类为ProxyFactoryBean这样的子类提供了配置属性。
- AdvisedSupport:封装了AOP对通知和通知器的相关操作,这些操作对于不同的AOP的代理对象的生成都是一样的,对于具体的AOP代理对象的创建,AdvisedSupport把它交给它的子类们去完成。
- ProxyCreatorSupport:可以看作是其子类创建AOP代理对象的一个辅助类。
- AspectJProxyFactory、ProxyFactory、ProxyFactoryBean:分别是具体AOP代理对象生成的类。对于需要使用AspectJ的AOP应用,AspectJProxyFactory起到了集成Spring和AspectJ的作用;对于使用Spring AOP的应用,ProxyFactoryBean和ProxyFactory都提供了AOP功能的封装,不同在于ProxyFactoryBean提供了IoC容器声明式配置,而ProxyFactory需要编程式的使用Spring AOP的功能。
- AbstractSingletonProxyFactoryBean:抽象类,用于只生成单例的代理工厂bean。
- TransactionProxyFactoryBean:简化的声明式事务处理的代理工厂bean。
具体的AOP代理对象的生成,可以根据不同需要,采取上述的一些实现类去生成,在这里我们以ProxyFactoryBean作为例子来具体看看Spring AOP代理对象的生成。ProxyFactoryBean继承了FactoryBean,它是一个工厂bean,我们知道工厂bean实例化的时候回调用到getObject()方法
public Object getObject() throws BeansException { //初始化Advisor链 initializeAdvisorChain(); if (isSingleton()) { //单例 return getSingletonInstance(); } else { if (this.targetName == null) { logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " + "Enable prototype proxies by setting the 'targetName' property."); } //非单例 return newPrototypeInstance(); } }
1. 初始化advisor链
initializeAdvisorChain()所做的工作很简单,就是将ProxyFactoryBean配置中的interceptorNames列表加入到advisors列表中(其中的advice将会自动封装成advisor)。
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException { if (this.advisorChainInitialized) { return; } if (!ObjectUtils.isEmpty(this.interceptorNames)) { if (this.beanFactory == null) { throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " + "- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames)); } // Globals can't be last unless we specified a targetSource using the property... if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) && this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) { throw new AopConfigException("Target required after globals"); } // 这里是添加Advisor链的调用,是通过interceptorNames属性进行配置的 for (int i = 0; i < this.interceptorNames.length; i++) { String name = this.interceptorNames[i]; if (logger.isTraceEnabled()) { logger.trace("Configuring advisor or advice '" + name + "'"); } if (name.endsWith(GLOBAL_SUFFIX)) { if (!(this.beanFactory instanceof ListableBeanFactory)) { throw new AopConfigException( "Can only use global advisors or interceptors with a ListableBeanFactory"); } addGlobalAdvisor((ListableBeanFactory) this.beanFactory, name.substring(0, name.length() - GLOBAL_SUFFIX.length())); } else { Object advice = null; //singletion类型bean if (this.singleton || this.beanFactory.isSingleton(this.interceptorNames[i])) { // Add the real Advisor/Advice to the chain. advice = this.beanFactory.getBean(this.interceptorNames[i]); } else { //对prototype类型的bean的处理 advice = new PrototypePlaceholderAdvisor(this.interceptorNames[i]); } //将advisor加入到advisor链中,其中advice会被封装成advisor后添加 addAdvisorOnChainCreation(advice, this.interceptorNames[i]); } } } this.advisorChainInitialized = true; }
具体的过程会调用到
//advisorAdapterRegistry实例是DefaultAdvisorAdapterRegistry对象 this.advisorAdapterRegistry.wrap(next);
DefaultAdvisorAdapterRegistry对象用于注册AdviceAdapter对象,每一种AdviceAdapter用于判断advice是不是属于该AdviceAdapter所对应的advice以及用于将advice转换成相应的拦截器。Spring中一种advice都有相应与之对应的AdviceAdapter和拦截器对应。
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable { private final List adapters = new ArrayList(3); //注册已知的AdviceAdapter,每一种advice对应一种AdviceAdapter,Spring AOP默认提供了下面三种AdviceAdapter public DefaultAdvisorAdapterRegistry() { registerAdvisorAdapter(new MethodBeforeAdviceAdapter()); registerAdvisorAdapter(new AfterReturningAdviceAdapter()); registerAdvisorAdapter(new ThrowsAdviceAdapter()); } //这里就是将advice封装成advisor public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException { //如果已经是advisor对象了,就直接返回 if (adviceObject instanceof Advisor) { return (Advisor) adviceObject; } if (!(adviceObject instanceof Advice)) { throw new UnknownAdviceTypeException(adviceObject); } Advice advice = (Advice) adviceObject; //如果这个advice已经是一个拦截器了, if (advice instanceof MethodInterceptor) { // So well-known it doesn't even need an adapter. return new DefaultPointcutAdvisor(advice); } for (int i = 0; i < this.adapters.size(); i++) { // Check that it is supported. AdvisorAdapter adapter = (AdvisorAdapter) this.adapters.get(i); if (adapter.supportsAdvice(advice)) { return new DefaultPointcutAdvisor(advice); } } throw new UnknownAdviceTypeException(advice); } public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { List interceptors = new ArrayList(3); Advice advice = advisor.getAdvice(); if (advice instanceof MethodInterceptor) { interceptors.add(advice); } //通过adapter将advice封装成对应的拦截器 for (int i = 0; i < this.adapters.size(); i++) { AdvisorAdapter adapter = (AdvisorAdapter) this.adapters.get(i); if (adapter.supportsAdvice(advice)) { interceptors.add(adapter.getInterceptor(advisor)); } } if (interceptors.isEmpty()) { throw new UnknownAdviceTypeException(advisor.getAdvice()); } return (MethodInterceptor[]) interceptors.toArray(new MethodInterceptor[interceptors.size()]); } public void registerAdvisorAdapter(AdvisorAdapter adapter) { this.adapters.add(adapter); } }
现在我们就以MethodBeforeAdvice为例子来看看advice对应的Adapter以及Interceptor长的什么样子
//MethodBeforeAdvice对应的MethodBeforeAdviceAdapter class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable { //判断是不是MethodBeforeAdvice public boolean supportsAdvice(Advice advice) { return (advice instanceof MethodBeforeAdvice); } //将MethodBeforeAdvice封装成MethodBeforeAdviceInterceptor public MethodInterceptor getInterceptor(Advisor advisor) { MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice(); return new MethodBeforeAdviceInterceptor(advice); } } //MethodBeforeAdvice对应的MethodBeforeAdviceInterceptor public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable { private MethodBeforeAdvice advice; //通过MethodBeforeAdvice封装成拦截器 public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; } //拦截器主要的调用逻辑,MethodBeforeAdviceInterceptor的逻辑很简单,就是在调用方法之前,先调用MethodBeforeAdvice的before方法 public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); return mi.proceed(); } }
上面我们已经讲了初始化advisor链的过程中,只是简单的将advisor加入到advisor链中,其中如果传进去的是一个advice,则通过DefaultAdvisorAdapterRegistry这个一个默认实现将advice封装成advisor然后加入到advisor链中(DefaultAdvisorAdapterRegistry通过注册在对象里面的AdviceAdapter来判断是否是支持的advice类型)。我们都知道Spring AOP使用到了代理以及拦截器技术,上面我也讲了Advice、AdviceAdaptor以及AdviceInterceptor之间的关系,代理对象中只是将advice封装成了advisor,这么做的好处是什么呢?等整个AOP过程分析完之后,再做讨论。
2.代理对象生成
代理对象的生成就是通过AopProxy取得的,在Spring AOP中提供了两种方式的AopProxy:jdk的AopProxy和CGLIB的AopProxy,分别为JdkDynamicAopProxy和Cglib2AopProxy。具体采用哪种方式的AopProxy呢?
首先,我们在看看上面ProxyFactoryBean中提供的getObject()方法,取得实例的两种情况:Singleton和Prototype。不管哪种方式,我们看到,取得AopProxy的方式都是通过调用到AopProxyFactory接口的默认实现类DefaultAopProxyFactory中的createAopProxy方法
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()) { return new JdkDynamicAopProxy(config); } if (!cglibAvailable) { throw new AopConfigException( "Cannot proxy target class because CGLIB2 is not available. " + "Add CGLIB to the class path or specify proxy interfaces."); } return CglibProxyFactory.createCglibProxy(config); } else { return new JdkDynamicAopProxy(config); } }
从上面代码我们可以很清楚的看到Spring AOP才用两种方式生成代理的条件,默认采取jdk动态代理,如果这个类没有接口或者在config中配置了满足上述条件的属性,那么就走cglib的方式,当然如果目标类本身就是接口,那么也走jdk动态代理(其中的原因是cglib采取的继承的方式)。
接下来,通过AopProxy取得代理对象的过程就是jdk以及cglib如何生成代理对象的过程了,在这里我们不做讨论。
protected Object getProxy(AopProxy aopProxy) { //通过jdk或者cglib类型的AopProxy取得代理对象 return aopProxy.getProxy(this.proxyClassLoader); }
二、代理方法的调用
JdkDynamicAopProxy生成代理对象的时候,会将this作为参数传入,这里的this指的是InvocationHandler类型的参数,因为JdkDynamicAopProxy实现了InvocationHandler接口,重写了invoke方法
Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);根据jdk动态代理的知识,我们可以知道,代理方法在被调用的时候会调用到JdkDynamicAopProxy中的invoke方法。cglib也会以类似的形式调用到相应拦截器中的intercept方法,在这里我们以JdkDynamicAopProxy为例子来详细看看Spring AOP代理方法调用的过程。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation = null; Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Class targetClass = null; Object target = null; try { //如果是equals方法、hashCode方法,并且没有定义equals、hashCode方法,就直接调用目标类中的 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { return (equals(args[0]) ? Boolean.TRUE : Boolean.FALSE); } if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { return new Integer(hashCode()); } //通过反射调用 if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal = null; if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // May be <code>null</code>. Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. target = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); } //取得方法对应的拦截器(在这里会调用到DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法,这个方法中会生成拦截器) List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); //如果这个方法的拦截器链为空,那么直接以反射的方式调用目标对象的该方法 if (chain.isEmpty()) { retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); } else { //创建一个method invocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); //执行 retVal = invocation.proceed(); } if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { retVal = proxy; } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
在代理方法调用的过程中,会根据advisor获得该方法的所有拦截器,上述取得拦截器链的方法会最总调用到DefaultAdvisorChainFactory中的getInterceptorsAndDynamicInterceptionAdvice方法。
public List getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, Class targetClass) { List interceptorList = new ArrayList(config.getAdvisors().length); //判断是否存在有Introduction boolean hasIntroductions = hasMatchingIntroductions(config, targetClass); AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); Advisor[] advisors = config.getAdvisors(); for (int i = 0; i < advisors.length; i++) { Advisor advisor = advisors[i]; //生成方法的拦截器,Pointcut类型处理方式 if (advisor instanceof PointcutAdvisor) { // Add it conditionally. PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor; if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) { MethodInterceptor[] interceptors = registry.getInterceptors(advisor); MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher(); if (MethodMatchers.matches(mm, method, targetClass, hasIntroductions)) { if (mm.isRuntime()) { // Creating a new object instance in the getInterceptors() method // isn't a problem as we normally cache created chains. for (int j = 0; j < interceptors.length; j++) { interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptors[j], mm)); } } else { interceptorList.addAll(Arrays.asList(interceptors)); } } } } //生成方法拦截器,Introduction的处理方式 else if (advisor instanceof IntroductionAdvisor) { IntroductionAdvisor ia = (IntroductionAdvisor) advisor; if (config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } else { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } return interceptorList; } private static boolean hasMatchingIntroductions(Advised config, Class targetClass) { for (int i = 0; i < config.getAdvisors().length; i++) { Advisor advisor = config.getAdvisors()[i]; if (advisor instanceof IntroductionAdvisor) { IntroductionAdvisor ia = (IntroductionAdvisor) advisor; if (ia.getClassFilter().matches(targetClass)) { return true; } } } return false; }
拦截器的运行
public Object proceed() throws Throwable { //拦截器调用完毕之后调用target方法 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); } }
上面会调用到拦截器的invoke方法,然后通过查看各种拦截器的invoke方法,我们可以看到拦截器链中的拦截器会被执行到,并且各个拦截器中的advice方法能保持预期的顺序执行到。
//MethodBeforeAdviceInterceptor //调用接下来的拦截器之前先调用before方法 public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); return mi.proceed(); } //AfterReturningAdviceInterceptor //调用剩下的拦截器之后再调用after方法 public Object invoke(MethodInvocation mi) throws Throwable { Object retVal = mi.proceed(); this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis()); return retVal; } //ThrowsAdviceInterceptor //调用方法发生异常时执行到,注意:捕获之后接着往上抛出去 public Object invoke(MethodInvocation mi) throws Throwable { public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); } catch (Throwable ex) { Method handlerMethod = getExceptionHandler(ex); if (handlerMethod != null) { invokeHandlerMethod(mi, ex, handlerMethod); } throw ex; } } try { return mi.proceed(); } catch (Throwable ex) { Method handlerMethod = getExceptionHandler(ex); if (handlerMethod != null) { invokeHandlerMethod(mi, ex, handlerMethod); } throw ex; } }
这样 我们看到Spring AOP的整个流程。