在前文Spring IOC容器建立bean過程淺析已經介紹了Spring IOC建立初始化bean的大體過程。如今對Spring的AOP實現機制進行研究分析。html
名詞 | 概念 |
---|---|
Advice | 通知,在鏈接點的處理邏輯 |
Advisor | Advisor能夠簡單理解爲Advice+PointCut |
Interceptor | 攔截器 |
Aspect | 切面 |
AbstractAutoProxyCreator是Spring AOP實現的一個很重要的抽象類。下面是它的繼承層次。
java
咱們能夠注意到,它實際上是一個BeanPostProcessor。咱們須要重點關注的方法是其中的wrapIfNecessary方法,能夠說這是Spring實現Bean代理的核心方法。
wrapIfNecessary在兩處會被調用,一處是getEarlyBeanReference,另外一處是postProcessAfterInitialization。spring
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (beanName != null && this.targetSourcedBeans.contains(beanName)) { return bean; } // 判斷是否不該該代理這個bean。 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } /* * 判斷是不是一些InfrastructureClass或者是否應該跳過這個bean。 * 所謂InfrastructureClass就是指Advice/PointCut/Advisor等接口的實現類。 * shouldSkip默認實現爲返回false,因爲是protected方法,子類能夠覆蓋。 */ if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // 獲取這個bean的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; } // 這個bean不須要被代理。 this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); } ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); if (!proxyFactory.isProxyTargetClass()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); for (Advisor advisor : advisors) { proxyFactory.addAdvisor(advisor); } proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(getProxyClassLoader()); }
從上面的createProxy方法中,咱們能夠看到,最終Spring是經過ProxyFactory#getProxy的調用來獲取最終的代理bean的。
下面就來看一下這其中的過程。app
public Object getProxy(ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); } /** * 該方法是ProxyCreatorSupport(ProxyFactory的基類)的保護方法。 */ protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } return getAopProxyFactory().createAopProxy(this); }
DefaultAopProxyFactory是AopProxyFactory接口的默認實現,下面來看一下其中createAopProxy方法的實現。Spring就是在這裏判斷是使用JDK動態代理仍是cglib代理的。ide
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { /* * 這裏是Spring判斷是用JDK動態代理仍是Cglib代理的依據。 * 1. optimize開關被設置爲true。此開關默認爲false。 * 2. proxyTargetClass開關爲true。 * 3. 沒有用戶代理接口。所謂用戶代理接口就是指非Spring生成的代理。 * * 知足上述三點任意一點就會根據代理類自己 */ 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."); } // 若是targetClass自己是個接口或者targetClass是JDK Proxy生成的,則使用JDK動態代理。 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } // 不然使用Cglib代理。 return new ObjenesisCglibAopProxy(config); } else { // 使用JDK動態代理。 return new JdkDynamicAopProxy(config); } }
public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource()); } Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
能夠看到本質上JdkDynamicAopProxy對於AopProxy的getProxy方法的實現本質上是調用咱們熟悉的Proxy.newProxyInstance來生成代理bean。
而JdkDynamicAopProxy自己也實現了InvocationHandler接口。下面就來看下它對InvocationHandler#invoke的實現。源碼分析
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation; Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Class<?> targetClass = null; Object target = null; try { if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // 方法爲equals且代理bean自己沒有實現equals方法。 return equals(args[0]); } else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // 方法爲hashCode且代理bean自己沒有實現hashCode方法。 return hashCode(); } else if (method.getDeclaringClass() == DecoratingProxy.class) { return AopProxyUtils.ultimateTargetClass(this.advised); } else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; if (this.advised.exposeProxy) { oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } target = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); } // 獲取該方法對應的攔截器鏈。 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // 若是沒有任何攔截器,則經過反射調用對應方法。 if (chain.isEmpty()) { Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // 建立方法調用鏈。 invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // 調用方法聯。 retVal = invocation.proceed(); } Class<?> returnType = method.getReturnType(); // 若是返回的是this,則判斷是否須要把retVal設置爲代理對象。 if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { 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; } finally { if (target != null && !targetSource.isStatic()) { targetSource.releaseTarget(target); } if (setProxyContext) { AopContext.setCurrentProxy(oldProxy); } } }
Spring對於cglib建立代理,內部默認使用ObjenesisCglibAopProxy來建立代理bean,它是CglibAopProxy的子類,而且重寫了createProxyClassAndInstance方法。Objenesis是一個類庫,能夠繞過構造器建立對象。
cglib使用Enhancer來生成代理類,生成的類實質上是被代理類的子類。更多關於Enhancer的信息,能夠參考個人博文cglib之Enhancer。post
public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource()); } try { // advised其實就是建立CglibAopProxy的時候構造參數中傳遞的config配置。 Class<?> rootClass = this.advised.getTargetClass(); Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); Class<?> proxySuperClass = rootClass; if (ClassUtils.isCglibProxyClass(rootClass)) { proxySuperClass = rootClass.getSuperclass(); Class<?>[] additionalInterfaces = rootClass.getInterfaces(); for (Class<?> additionalInterface : additionalInterfaces) { this.advised.addInterface(additionalInterface); } } validateClassIfNecessary(proxySuperClass, classLoader); Enhancer enhancer = createEnhancer(); if (classLoader != null) { enhancer.setClassLoader(classLoader); if (classLoader instanceof SmartClassLoader && ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) { enhancer.setUseCache(false); } } // 配置enhancer如代理接口,回調等。 enhancer.setSuperclass(proxySuperClass); enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); // 這裏生成callback方法的邏輯是閱讀源碼的重點。 Callback[] callbacks = getCallbacks(rootClass); Class<?>[] types = new Class<?>[callbacks.length]; for (int x = 0; x < types.length; x++) { types[x] = callbacks[x].getClass(); } // callbackFilter的做用主要是創建了method與callback編號的映射。 enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); enhancer.setCallbackTypes(types); // 生成代理的class以及代理bean實例。 return createProxyClassAndInstance(enhancer, callbacks); } catch (CodeGenerationException ex) { throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: " + "Common causes of this problem include using a final class or a non-visible class", ex); } catch (IllegalArgumentException ex) { throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: " + "Common causes of this problem include using a final class or a non-visible class", ex); } catch (Exception ex) { throw new AopConfigException("Unexpected AOP exception", ex); } }
在CglibAopProxy內部定義了一組常量用於表示生成的callback索引。優化
接下來就看一下這些callback生成的具體源碼實現。ui
private Callback[] getCallbacks(Class<?> rootClass) throws Exception { // Parameters used for optimisation choices... boolean exposeProxy = this.advised.isExposeProxy(); boolean isFrozen = this.advised.isFrozen(); boolean isStatic = this.advised.getTargetSource().isStatic(); // 對於AOP方法的調用,使用DynamicAdvisedInterceptor攔截器。 Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised); /* * 不須要加強,但可能會返回this的方法: * 若是targetSource是靜態的話(每次getTarget都是同一個對象),使用StaticUnadvisedExposedInterceptor * 不然使用DynamicUnadvisedExposedInterceptor。 * */ Callback targetInterceptor; if (exposeProxy) { targetInterceptor = isStatic ? new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) : new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()); } /* * 這裏的分支邏輯與上面相同,只不過exposeProxy爲false的狀況下不會設置AopContext中的currentProxy。 */ else { targetInterceptor = isStatic ? new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) : new DynamicUnadvisedInterceptor(this.advised.getTargetSource()); } Callback targetDispatcher = isStatic ? new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp(); Callback[] mainCallbacks = new Callback[] { // AOP攔截器。 aopInterceptor, targetInterceptor, new SerializableNoOp(), targetDispatcher, this.advisedDispatcher, new EqualsInterceptor(this.advised), new HashCodeInterceptor(this.advised) }; Callback[] callbacks; /* * 若是targetSource爲靜態而且配置已經凍結(advice不會改變),能夠封裝到FixedChainStaticTargetInterceptor來攔截調用方法。 * 其實FixedChainStaticTargetInterceptor裏的邏輯就至關於對固定的target每次建立CglibMethodInvocation來實現aop攔截。 */ if (isStatic && isFrozen) { Method[] methods = rootClass.getMethods(); Callback[] fixedCallbacks = new Callback[methods.length]; this.fixedInterceptorMap = new HashMap<String, Integer>(methods.length); for (int x = 0; x < methods.length; x++) { List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass); fixedCallbacks[x] = new FixedChainStaticTargetInterceptor( chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass()); this.fixedInterceptorMap.put(methods[x].toString(), x); } // 把mainCallbacks和fixedCallbacks拼起來。 callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length]; System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length); System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length); this.fixedInterceptorOffset = mainCallbacks.length; } else { callbacks = mainCallbacks; } return callbacks; }
咱們這裏主要看ProxyCallbackFilter#accept方法的源碼實現。this
public int accept(Method method) { // finalize方法使用SerializableNoOp if (AopUtils.isFinalizeMethod(method)) { logger.debug("Found finalize() method - using NO_OVERRIDE"); return NO_OVERRIDE; } if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { if (logger.isDebugEnabled()) { logger.debug("Method is declared on Advised interface: " + method); } return DISPATCH_ADVISED; } // equals方法使用EqualsInterceptor。 if (AopUtils.isEqualsMethod(method)) { logger.debug("Found 'equals' method: " + method); return INVOKE_EQUALS; } // hashCode方法使用HashCodeInterceptor。 if (AopUtils.isHashCodeMethod(method)) { logger.debug("Found 'hashCode' method: " + method); return INVOKE_HASHCODE; } Class<?> targetClass = this.advised.getTargetClass(); List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); boolean haveAdvice = !chain.isEmpty(); boolean exposeProxy = this.advised.isExposeProxy(); boolean isStatic = this.advised.getTargetSource().isStatic(); boolean isFrozen = this.advised.isFrozen(); if (haveAdvice || !isFrozen) { // 有advice,配置沒有凍結,且須要暴露proxy,使用DynamicAdvisedInterceptor。 if (exposeProxy) { if (logger.isDebugEnabled()) { logger.debug("Must expose proxy on advised method: " + method); } return AOP_PROXY; } String key = method.toString(); // 若是知足優化條件(targetSource靜態且配置凍結),則嘗試使用fixedInterceptor。 if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) { if (logger.isDebugEnabled()) { logger.debug("Method has advice and optimisations are enabled: " + method); } // 從fixedInterceptorMap中拿到編號加上偏移量便可。 int index = this.fixedInterceptorMap.get(key); return (index + this.fixedInterceptorOffset); } else { if (logger.isDebugEnabled()) { logger.debug("Unable to apply any optimisations to advised method: " + method); } return AOP_PROXY; } } else { /* * 若是須要暴露proxy或者targetSource非靜態,則使用的callback多是下面三種之一。 * StaticUnadvisedExposedInterceptor * DynamicUnadvisedExposedInterceptor * DynamicUnadvisedInterceptor */ if (exposeProxy || !isStatic) { return INVOKE_TARGET; } Class<?> returnType = method.getReturnType(); // 返回的類型與targetClass一致(有可能返回this),使用StaticUnadvisedInterceptor。 if (targetClass == returnType) { if (logger.isDebugEnabled()) { logger.debug("Method " + method + "has return type same as target type (may return this) - using INVOKE_TARGET"); } return INVOKE_TARGET; } // 返回類型爲基本類型或者targetClass不兼容於返回類型(不可能返回this),使用StaticDispatcher。 else if (returnType.isPrimitive() || !returnType.isAssignableFrom(targetClass)) { if (logger.isDebugEnabled()) { logger.debug("Method " + method + " has return type that ensures this cannot be returned- using DISPATCH_TARGET"); } return DISPATCH_TARGET; } else { // 這種狀況targetClass是返回類型的子類(可能返回this),使用StaticUnadvisedInterceptor。 if (logger.isDebugEnabled()) { logger.debug("Method " + method + "has return type that is assignable from the target type (may return this) - " + "using INVOKE_TARGET"); } return INVOKE_TARGET; } } }
在spring中經過cglib建立的代理中,對於須要加強的方法設置的callback爲DynamicAdvisedInterceptor,它實現了cglib的MethodInterceptor。
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable { private final AdvisedSupport advised; public DynamicAdvisedInterceptor(AdvisedSupport advised) { this.advised = advised; } @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object oldProxy = null; boolean setProxyContext = false; Class<?> targetClass = null; Object target = null; try { if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // 拿出原始bean對象。 target = getTarget(); if (target != null) { targetClass = target.getClass(); } // 根據method和class從配置中獲取加強。 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); Object retVal; // 若是沒有加強而且方法爲public,則直接調用。 if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = methodProxy.invoke(target, argsToUse); } else { // 建立攔截器鏈並調用。 retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); } retVal = processReturnType(proxy, target, method, retVal); return retVal; } finally { if (target != null) { releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } } @Override public boolean equals(Object other) { return (this == other || (other instanceof DynamicAdvisedInterceptor && this.advised.equals(((DynamicAdvisedInterceptor) other).advised))); } @Override public int hashCode() { return this.advised.hashCode(); } protected Object getTarget() throws Exception { return this.advised.getTargetSource().getTarget(); } protected void releaseTarget(Object target) throws Exception { this.advised.getTargetSource().releaseTarget(target); } }
這裏來看一下方法攔截器的具體實現。這個類特別重要,它是JDK動態代理和cglib代理底層都會用到的類,也就是做用在方法上的加強鏈的本質。
public Object proceed() throws Throwable { // 邊界判斷,若是攔截器都調用完畢了就調用鏈接點方法。 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } // 迭代攔截器聯獲取當前的攔截器。 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; // 判斷是否和當前的切點匹配。 if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { // 若是不匹配的話,就遞歸調用proceed。 return proceed(); } } else { // 若是是一個MethodInterceptor的話則直接調用。 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
這是個很常見的問題,好比會有疑問爲何一個非事務方法調用事務方法沒有進入事務等等。下面經過源碼來分析緣由。
經過查看源碼能夠看到,Spring的cglib的AOP不管方法是否有加強,本質上都是對target
進行調用。這裏的target對於通常的AOP一般都是來源於
AbstractAutoProxyCreator#wrapIfNecessary中經過SingletonTargetSource包裝的入參bean,而不是cglib中實際生成的proxy對象。也就是說極可能target就是一個很樸素的bean。那麼進入到這樣一個bean中的方法天然不會再觸發cglib代理的callback攔截了。
其實能夠將代理看做是一個外殼,在方法被調用的時候會被攔截進入到殼子中寫好的邏輯,可是方法體自己已經脫離了外殼層,是在本體中運行的。
這個問題也是常常會困擾的問題,就是關於那些各類aop切方法,到底哪一個會先切,哪一個後切。
AbstractAutoProxyCreator#wrapIfNecessary中getAdvicesAndAdvisorsForBean用來抓取advice和advisor。
咱們以AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean的實現爲例:
注意到這其中是有排序的邏輯的,以AspectJAwareAdvisorAutoProxyCreator#sortAdvisors爲例能夠看到用的comparator是內置的默認比較器AspectJPrecedenceComparator。
不妨再看一下AspectJPrecedenceComparator的比較策略:
能夠看到會先使用內部的AnnotationAwareOrderComparator來比較,若是優先級相同,則再調用comparePrecedenceWithinAspect進行比較。
AnnotationAwareOrderComparator繼承自OrderComparator, 在OrderComparator中的判斷順序邏輯是若是任一對象是PriorityOrder接口的子類型,則具備更高優先級。不然調用getOrder方法比較。
注意,上面的排序規則只是影響了各advice的調用順序,並不表明咱們關注的aop實際邏輯的調用順序,好比AspectJAfterAdvice#invoke也是先對methodInvocation調用proceed再處理自己的後置邏輯。