轉載自: https://javadoop.com/post/spring-aop-source
之前寫過 IOC 的源碼分析,那篇文章真的有點長,看完需要點耐心。很多讀者希望能寫一寫 Spring AOP 的源碼分析文章,這樣讀者看完 IOC + AOP 也就對 Spring 會有比較深的理解了。今天終於成文了,可能很多讀者早就不再等待了,不過主要爲了後來者吧。
本文不會像 IOC 源碼分析那篇文章一樣,很具體地分析每一行 Spring AOP 的源碼,目標讀者是已經知道 Spring IOC 源碼是怎麼回事的讀者,因爲 Spring AOP 終歸是依賴於 IOC 容器來管理的。
閱讀建議:1、先搞懂 IOC 容器的源碼,AOP 依賴於 IOC 容器來管理。2、仔細看完 Spring AOP 使用介紹 這篇文章,先搞懂各種使用方式,你才能"猜到"應該怎麼實現。
Spring AOP 的源碼並不簡單,因爲它多,所以閱讀源碼最好就是找到一個分支,追蹤下去。本文定位爲走馬觀花,看個大概,不具體到每一個細節。
目錄:
這一節,我們先來"猜猜" Spring 是怎麼實現 AOP 的。
在 Spring 的容器中,我們面向的對象是一個個的 bean 實例,bean 是什麼?我們可以簡單理解爲是 BeanDefinition 的實例,Spring 會根據 BeanDefinition 中的信息爲我們生產合適的 bean 實例出來。
當我們需要使用 bean 的時候,通過 IOC 容器的 getBean(…) 方法從容器中獲取 bean 實例,只不過大部分的場景下,我們都用了依賴注入,所以很少手動調用 getBean(...) 方法。
Spring AOP 的原理很簡單,就是動態代理,它和 AspectJ 不一樣,AspectJ 是直接修改掉你的字節碼。
代理模式很簡單,接口 + 真實實現類 + 代理類,其中 真實實現類 和 代理類 都要實現接口,實例化的時候要使用代理類。所以,Spring AOP 需要做的是生成這麼一個代理類,然後替換掉真實實現類來對外提供服務。
替換的過程怎麼理解呢?在 Spring IOC 容器中非常容易實現,就是在 getBean(…) 的時候返回的實際上是代理類的實例,而這個代理類我們自己沒寫代碼,它是 Spring 採用 JDK Proxy 或 CGLIB 動態生成的。
getBean(…) 方法用於查找或實例化容器中的 bean,這也是爲什麼 Spring AOP 只能作用於 Spring 容器中的 bean 的原因,對於不是使用 IOC 容器管理的對象,Spring AOP 是無能爲力的。
閱讀源碼很好用的一個方法就是跑代碼來調試,因爲自己一行一行地看的話,比較枯燥,而且難免會漏掉一些東西。
下面,我們先準備一些簡單的調試用的代碼。
首先先定義兩個 Service 接口:
// OrderService.java public interface OrderService { Order createOrder(String username, String product); Order queryOrder(String username); } // UserService.java public interface UserService { User createUser(String firstName, String lastName, int age); User queryUser(); }
然後,分別來一個接口實現類:
// OrderServiceImpl.java public class OrderServiceImpl implements OrderService { @Override public Order createOrder(String username, String product) { Order order = new Order(); order.setUsername(username); order.setProduct(product); return order; } @Override public Order queryOrder(String username) { Order order = new Order(); order.setUsername("test"); order.setProduct("test"); return order; } } // UserServiceImpl.java public class UserServiceImpl implements UserService { @Override public User createUser(String firstName, String lastName, int age) { User user = new User(); user.setFirstName(firstName); user.setLastName(lastName); user.setAge(age); return user; } @Override public User queryUser() { User user = new User(); user.setFirstName("test"); user.setLastName("test"); user.setAge(20); return user; } }
寫兩個 Advice:
public class LogArgsAdvice implements MethodBeforeAdvice { @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("準備執行方法: " + method.getName() + ", 參數列表:" + Arrays.toString(args)); } }
public class LogResultAdvice implements AfterReturningAdvice { @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println(method.getName() + "方法返回:" + returnValue); } }
配置一下:
我們這邊使用了前面文章介紹的配置 Advisor 的方式,我們回顧一下。
每個 advisor 內部持有 advice 實例,advisor 負責匹配,內部的 advice 負責實現攔截處理。配置了各個 advisor 後,配置 DefaultAdvisorAutoProxyCreator 使得所有的 advisor 配置自動生效。
啓動:
public class SpringAopSourceApplication { public static void main(String[] args) { // 啓動 Spring 的 IOC 容器 ApplicationContext context = new ClassPathXmlApplicationContext("classpath:DefaultAdvisorAutoProxy.xml"); UserService userService = context.getBean(UserService.class); OrderService orderService = context.getBean(OrderService.class); userService.createUser("Tom", "Cruise", 55); userService.queryUser(); orderService.createOrder("Leo", "隨便買點什麼"); orderService.queryOrder("Leo"); } }
輸出:
準備執行方法: createUser, 參數列表:[Tom, Cruise, 55] queryUser方法返回:User{firstName='test', lastName='test', age=20, address='null'} 準備執行方法: createOrder, 參數列表:[Leo, 隨便買點什麼] queryOrder方法返回:Order{username='test', product='test'}
從輸出結果,我們可以看到:
LogArgsAdvice 作用於 UserService#createUser(…) 和 OrderService#createOrder(…) 兩個方法;
LogResultAdvice 作用於 UserService#queryUser() 和 OrderService#queryOrder(…) 兩個方法;
下面的代碼分析中,我們將基於這個簡單的例子來介紹。
本節介紹 Spring AOP 是怎麼作用於 IOC 容器中的 bean 的。
Spring AOP 的使用介紹 那篇文章已經介紹過 DefaultAdvisorAutoProxyCreator 類了,它能實現自動將所有的 advisor 生效。
我們來追蹤下 DefaultAdvisorAutoProxyCreator 類,看看它是怎麼一步步實現的動態代理。然後在這個基礎上,我們再簡單追蹤下 @AspectJ 配置方式下的源碼實現。
首先,先看下 DefaultAdvisorAutoProxyCreator 的繼承結構:
我們可以發現,DefaultAdvisorAutoProxyCreator 最後居然是一個 BeanPostProcessor,在 Spring IOC 源碼分析的時候說過,BeanPostProcessor 的兩個方法,分別在 init-method 的前後得到執行。
public interface BeanPostProcessor { Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; }
這裏再貼一下 IOC 的源碼,我們回顧一下:
// AbstractAutowireCapableBeanFactory
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { // 1. 創建實例 instanceWrapper = createBeanInstance(beanName, mbd, args); } ... // Initialize the bean instance. Object exposedObject = bean; try { // 2. 裝載屬性 populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) { // 3. 初始化 exposedObject = initializeBean(beanName, exposedObject, mbd); } } ... }
在上面第 3 步 initializeBean(...) 方法中會調用 BeanPostProcessor 中的方法,如下:
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { ... Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { // 1. 執行每一個 BeanPostProcessor 的 postProcessBeforeInitialization 方法 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { // 調用 bean 配置中的 init-method="xxx" invokeInitMethods(beanName, wrappedBean, mbd); } ... if (mbd == null || !mbd.isSynthetic()) { // 我們關注的重點是這裏!!! // 2. 執行每一個 BeanPostProcessor 的 postProcessAfterInitialization 方法 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
也就是說,Spring AOP 會在 IOC 容器創建 bean 實例的最後對 bean 進行處理。其實就是在這一步進行代理增強。
我們回過頭來,DefaultAdvisorAutoProxyCreator 的繼承結構中,postProcessAfterInitialization() 方法在其父類 AbstractAutoProxyCreator 這一層被覆寫了:
// AbstractAutoProxyCreator
@Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
繼續往裏看 wrapIfNecessary(...) 方法,這個方法將返回代理類(如果需要的話):
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (beanName != null && this.targetSourcedBeans.contains(beanName)) { return bean; } if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // 返回匹配當前 bean 的所有的 advisor、advice、interceptor // 對於本文的例子,"userServiceImpl" 和 "OrderServiceImpl" 這兩個 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; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }
這裏有兩個點提一下:
getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null),這個方法將得到所有的可用於攔截當前 bean 的advisor、advice、interceptor。
另一個就是 TargetSource 這個概念,它用於封裝真實實現類的信息,上面用了 SingletonTargetSource 這個實現類,其實我們這裏也不太需要關心這個,知道有這麼回事就可以了。
我們繼續往下看 createProxy(…) 方法:
// 注意看這個方法的幾個參數, // 第三個參數攜帶了所有的 advisors // 第四個參數 targetSource 攜帶了真實實現的信息 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 proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); // 在 schema-based 的配置方式中,我們介紹過,如果希望使用 CGLIB 來代理接口,可以配置 // proxy-target-class="true",這樣不管有沒有接口,都使用 CGLIB 來生成代理: // <aop:config proxy-target-class="true">......</aop:config> if (!proxyFactory.isProxyTargetClass()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { // 點進去稍微看一下代碼就知道了,主要就兩句: // 1. 有接口的,調用一次或多次:proxyFactory.addInterface(ifc); // 2. 沒有接口的,調用:proxyFactory.setProxyTargetClass(true); evaluateProxyInterfaces(beanClass, proxyFactory); } } // 這個方法會返回匹配了當前 bean 的 advisors 數組 // 對於本文的例子,"userServiceImpl" 和 "OrderServiceImpl" 到這邊的時候都會返回兩個 advisor // 注意:如果 specificInterceptors 中有 advice 和 interceptor,它們也會被包裝成 advisor,進去看下源碼就清楚了 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()); }
我們看到,這個方法主要是在內部創建了一個 ProxyFactory 的實例,然後 set 了一大堆內容,剩下的工作就都是這個 ProxyFactory 實例的了,通過這個實例來創建代理: getProxy(classLoader)
。
根據上面的源碼,我們走到了 ProxyFactory 這個類了,我們到這個類來一看究竟。
順着上面的路子,我們首先到 ProxyFactory#getProxy(classLoader) 方法:
public Object getProxy(ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); }
該方法首先通過 createAopProxy() 創建一個 AopProxy 的實例:
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } return getAopProxyFactory().createAopProxy(this); }
創建 AopProxy 之前,我們需要一個 AopProxyFactory 實例,然後看 ProxyCreatorSupport 的構造方法:
public ProxyCreatorSupport() { this.aopProxyFactory = new DefaultAopProxyFactory(); }
這樣就將我們導到 DefaultAopProxyFactory
這個類了,我們看它的 createAopProxy(…) 方法:
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { @Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { // (我也沒用過這個optimize,默認false) || (proxy-target-class=true) || (沒有接口) 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."); } // 如果要代理的類本身就是接口,也會用 JDK 動態代理 // 我也沒用過這個。。。 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { // 如果有接口,會跑到這個分支 return new JdkDynamicAopProxy(config); } } // 判斷是否有實現自定義的接口 private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) { Class<?>[] ifcs = config.getProxiedInterfaces(); return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0]))); } }
到這裏,我們知道 createAopProxy 方法有可能返回 JdkDynamicAopProxy 實例,也有可能返回 ObjenesisCglibAopProxy 實例,這裏總結一下:
如果被代理的目標類實現了一個或多個自定義的接口,那麼就會使用 JDK 動態代理,如果沒有實現任何接口,會使用 CGLIB 實現代理,如果設置了 proxy-target-class="true",那麼都會使用 CGLIB。
JDK 動態代理基於接口,所以只有接口中的方法會被增強,而 CGLIB 基於類繼承,需要注意就是如果方法使用了 final 修飾,或者是 private 方法,是不能被增強的。
有了 AopProxy 實例以後,我們就回到這個方法了:
public Object getProxy(ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); }
我們分別來看下兩個 AopProxy 實現類的 getProxy(classLoader) 實現。
JdkDynamicAopProxy 類的源碼比較簡單,總共兩百多行,
@Override 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); }
java.lang.reflect.Proxy.newProxyInstance(…) 方法需要三個參數,第一個是 ClassLoader,第二個參數代表需要實現哪些接口,第三個參數最重要,是 InvocationHandler 實例,我們看到這裏傳了 this,因爲 JdkDynamicAopProxy 本身實現了 InvocationHandler 接口。
InvocationHandler 只有一個方法,當生成的代理類對外提供服務的時候,都會導到這個方法中:
public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }
下面來看看 JdkDynamicAopProxy 對其的實現:
@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)) { // The target does not implement the equals(Object) method itself. // 代理的 equals 方法 return equals(args[0]); } else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. // 代理的 hashCode 方法 return hashCode(); } else if (method.getDeclaringClass() == DecoratingProxy.class) { // There is only getDecoratedClass() declared -> dispatch to proxy config. // return AopProxyUtils.ultimateTargetClass(this.advised); } else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // Service invocations on ProxyConfig with the proxy config... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; // 如果設置了 exposeProxy,那麼將 proxy 放到 ThreadLocal 中 if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // May be null. 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(); } // Get the interception chain for this method. // 創建一個 chain,包含所有要執行的 advice List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // Check whether we have any advice. If we don't, we can fallback on direct // reflective invocation of the target, and avoid creating a MethodInvocation. if (chain.isEmpty()) { // We can skip creating a MethodInvocation: just invoke the target directly // Note that the final invoker must be an InvokerInterceptor so we know it does // nothing but a reflective operation on the target, and no hot swapping or fancy proxying. // chain 是空的,說明不需要被增強,這種情況很簡單 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // We need to create a method invocation... // 執行方法,得到返回值 invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain. retVal = invocation.proceed(); } // Massage return value if necessary. Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // Special case: it returned "this" and the return type of the method // is type-compatible. Note that we can't help if the target sets // a reference to itself in another returned object. 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()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
上面就三言兩語說了一下,感興趣的讀者自己去深入探索下,不是很難。簡單地說,就是在執行每個方法的時候,判斷下該方法是否需要被一次或多次增強(執行一個或多個 advice)。
說完了 JDK 動態代理 JdkDynamicAopProxy#getProxy(classLoader),我們再來瞄一眼 CGLIB 的代理實現 ObjenesisCglibAopProxy#getProxy(classLoader)。
ObjenesisCglibAopProxy 繼承了 CglibAopProxy,而 CglibAopProxy 繼承了 AopProxy。
ObjenesisCglibAopProxy 使用了 Objenesis 這個庫,和 cglib 一樣,我們不需要在 maven 中進行依賴,因爲 spring-core.jar 直接把它的源代碼也搞過來了。
通過 CGLIB 生成代理的代碼量有點大,我們就不進行深入分析了,我們看下大體的骨架。它的 getProxy(classLoader) 方法在父類 CglibAopProxy 類中:
// CglibAopProxy#getProxy(classLoader)
@Override public Object getProxy(ClassLoader classLoader) { ... // Configure CGLIB Enhancer... Enhancer enhancer = createEnhancer(); if (classLoader != null) { enhancer.setClassLoader(classLoader); if (classLoader instanceof SmartClassLoader && ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) { enhancer.setUseCache(false); } } enhancer.setSuperclass(proxySuperClass); enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); Callback[] callbacks = getCallbacks(rootClass); Class<?>[] types = new Class<?>[callbacks.length]; for (int x = 0; x < types.length; x++) { types[x] = callbacks[x].getClass(); } // fixedInterceptorMap only populated at this point, after getCallbacks call above enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); enhancer.setCallbackTypes(types); // Generate the proxy class and create a proxy instance. return createProxyClassAndInstance(enhancer, callbacks); } catch (CodeGenerationException ex) { ... } catch (IllegalArgumentException ex) { ... } catch (Throwable ex) { ... } }
CGLIB 生成代理的核心類是 Enhancer 類,這裏就不展開說了。
上面我們走馬觀花地介紹了使用 DefaultAdvisorAutoProxyCreator 來實現 Spring AOP 的源碼,這裏,我們也同樣走馬觀花地來看下 @AspectJ 的實現原理。
我們之前說過,開啓 @AspectJ 的兩種方式,一個是 <aop:aspectj-autoproxy/>
,一個是 @EnableAspectJAutoProxy
,它們的原理是一樣的,都是通過註冊一個 bean 來實現的。
解析 <aop:aspectj-autoproxy/>
需要用到 AopNamespaceHandler:
然後到類 AspectJAutoProxyBeanDefinitionParser:
class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser { @Override @Nullable public BeanDefinition parse(Element element, ParserContext parserContext) { AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element); extendBeanDefinition(element, parserContext); return null; } ... }
進去 registerAspectJAnnotationAutoProxyCreatorIfNecessary(...) 方法:
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary( parserContext.getRegistry(), parserContext.extractSource(sourceElement)); useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); registerComponentIfNecessary(beanDefinition, parserContext); }
再進去 AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(...):
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) { return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); }
最終我們看到,Spring 註冊了一個 AnnotationAwareAspectJAutoProxyCreator 的 bean,beanName 爲:"org.springframework.aop.config.internalAutoProxyCreator"。
我們看下 AnnotationAwareAspectJAutoProxyCreator 的繼承結構:
和前面介紹的 DefaultAdvisorAutoProxyCreator 一樣,它也是一個 BeanPostProcessor,剩下的我們就不說了,它和它的父類 AspectJAwareAdvisorAutoProxyCreator 都不復雜。
爲什麼要說這個呢?因爲我發現,很多人都以爲 Spring AOP 是通過這個接口來作用於 bean 生成代理的。
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor { Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException; boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException; PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException; }
它和 BeanPostProcessor 的方法非常相似,而且它還繼承了 BeanPostProcessor。
不仔細看還真的不好區分,下面是 BeanPostProcessor 中的兩個方法:
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
發現沒有,InstantiationAwareBeanPostProcessor 是 Instantiation
,BeanPostProcessor 是 Initialization
,它代表的是 bean 在實例化完成並且屬性注入完成,在執行 init-method 的前後進行作用的。
而 InstantiationAwareBeanPostProcessor 的執行時機要前面一些,大家需要翻下 IOC 的源碼:
// AbstractAutowireCapableBeanFactory 447行 protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException { ... try { // 讓 InstantiationAwareBeanPostProcessor 在這一步有機會返回代理 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } // BeanPostProcessor 是在這裏面實例化後才能得到執行 Object beanInstance = doCreateBean(beanName, mbdToUse, args); ... return beanInstance; }
點進去看 resolveBeforeInstantiation(beanName, mbdToUse) 方法,然後就會導到 InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation 方法,對於我們分析的 AOP 來說,該方法的實現在 AbstractAutoProxyCreator 類中:
@Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { ... if (beanName != null) { TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { this.targetSourcedBeans.add(beanName); Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } } return null; }
我們可以看到,這裏也有創建代理的邏輯,以至於很多人會搞錯。確實,這裏是有可能創建代理的,但前提是對於相應的 bean 我們有自定義的 TargetSource 實現,進到 getCustomTargetSource(...) 方法就清楚了,我們需要配置一個 customTargetSourceCreators,它是一個 TargetSourceCreator 數組。
這裏就不再展開說 TargetSource 了,請參考 Spring Reference 中的 Using TargetSources。