Spring AOP 源碼解析系列,建議你們按順序閱讀,歡迎討論spring
框架存在的意義,簡單來講就是將複雜的底層實現封裝起來,並提供便捷的外部接口供用戶使用。對於Spring AOP而言,不管是ProxyFactory仍是ProxyFactoryBean,都不能知足實際業務中複雜的應用,用戶不可能對每一個使用AOP代理的類進行配置。這時經過必定規則自動發現和代理天然應運而生。在spring-aop工程的autoproxy目錄構成了Spring AOP自動代理的基礎,AbstractAutoProxyCreator是自動代理實現的抽象基類,BeanNameAutoProxyCreator和DefaultAdvisorAutoProxyCreator則是Spring提供的兩個實現。數組
自動代理的實現原理同ProxyFactoryBean中使用FactoryBean擴展不一樣,而是經過BeanPostProcessor擴展對Bean對象的建立過程進行控制來實現AOP代理。抽象基類AbstractAutoProxyCreator實現了BeanPostProcessor的子接口SmartInstantiationAwareBeanPostProcessor。先來了解下這個子接口。緩存
咱們常說起的BeanPostProcessor擴展並非只有BeanPostProcessor一個接口,而是由其造成的多層接口體系,對Bean對象在IOC容器的建立過程的各個節點擴展造成的體系。這裏只展現下SmartInstantiationAwareBeanPostProcessor的類結構。app
BeanPostProcessor框架
InstantiationAwareBeanPostProcessoride
SmartInstantiationAwareBeanPostProcessor函數
而對於Spring AOP的自動代理,處理的階段有兩個,對象實例化前擴展和初始化後擴展。post
在對象實例化前(postProcessBeforeInstantiation)的擴展中,主要對配置了customTargetSourceCreators屬性的狀況進行處理,而默認的處理都是在初始化後(postProcessAfterInitialization)擴展裏執行的。ui
所謂的customTargetSourceCreators屬性是在AbstractAutoProxyCreator中的一個TargetSourceCreator數組,用來對代理對象target的封裝類TargetSource的生成進行自定義。spring內置的TargetSourceCreator有兩個:LazyInitTargetSourceCreator和QuickTargetSourceCreator。this
LazyInitTargetSourceCreator:建立的代理對象並無初始化,直到第一次調用時才進行初始化
QuickTargetSourceCreator:根據beanName的不一樣前綴建立三種經常使用的TargetSource類型(bean必須爲多例)
來看下核心代碼
if (beanName != null) { // 獲取自定義TargetSource 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; } }
第一步獲取定義TargetSource,即遍歷全部自定義TargetSourceCreator,調用getTargetSource方法返回TargetSource。
protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) { // We can't create fancy target sources for directly registered singletons. if (this.customTargetSourceCreators != null && this.beanFactory != null && this.beanFactory.containsBean(beanName)) { for (TargetSourceCreator tsc : this.customTargetSourceCreators) { TargetSource ts = tsc.getTargetSource(beanClass, beanName); if (ts != null) { // Found a matching TargetSource. if (logger.isDebugEnabled()) { logger.debug("TargetSourceCreator [" + tsc + " found custom TargetSource for bean with name '" + beanName + "'"); } return ts; } } } // No custom TargetSource found. return null; }
第二步獲取攔截器由子類實現,根據不一樣的方式獲取當前bean的攔截器,在後文以子類DefaultAdvisorAutoProxyCreator爲例詳細介紹。
第三步建立代理對象,經過建立ProxyFactory的方式完成,原理細節見ProxyFactory,來簡單看下它的實現。
protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { ProxyFactory proxyFactory = new ProxyFactory(); // copy代理配置,如proxyTargetClass,exposeProxy等 proxyFactory.copyFrom(this); // proxyTargetClass=false時 if (!proxyFactory.isProxyTargetClass()) { // 再次確認是否要代理類對象 if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } // 不須要則獲取其代理接口集合 else { evaluateProxyInterfaces(beanClass, proxyFactory); } } // 將全部攔截器封裝成Advisor Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); for (Advisor advisor : advisors) { proxyFactory.addAdvisor(advisor); } proxyFactory.setTargetSource(targetSource); // 擴展點,支持子類對ProxyFacory擴展 customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } // 建立代理對象 return proxyFactory.getProxy(getProxyClassLoader()); }
能夠說邏輯很是清晰,最後使用ProxyFactory建立代理對象也是使用ProxyFactory統一的API。若是最終返回的代理對象不爲空,則直接返回代理對象,再也不執行IOC中的對象屬性注入和初始化等操做了。
若是並無設置自定義TargetSourceCreator,代理對象就會在原始對象初始化完成後建立。
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; } // AOP體系的子類不被代理(Advisor,Advice等) if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // Create proxy if we have 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; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }
實現過程基本同以前的一直,由子類返回攔截器集合,建立ProxyFactory對象進行代理。
在基類AbstractAutoProxyCreator中經過BeanPostProcessor擴展的方式,使得bean在建立過程當中完成被代理。代理的框架已有AbstractAutoProxyCreator基本完成,留給子類的是獲取攔截器getAdvicesAndAdvisorsForBean方法的具體實現。咱們以DefaultAdvisorAutoProxyCreator爲例,瞭解下Spring AOP是如何完成自動發現和過濾切面的。
DefaultAdvisorAutoProxyCreator的獲取攔截器實現其實由其抽象基類AbstractAdvisorAutoProxyCreator實現。
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) { List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); }
實際操做有findEligibleAdvisors執行
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { // 尋找全部Advisor候選者 List<Advisor> candidateAdvisors = findCandidateAdvisors(); // 獲取匹配當前bean的Advisor List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { // 對Advisor排序 eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
主要過程分爲兩步,第一步尋找全部Advisor候選者,即自動發現切面,第二部篩選當前bean的Advisor。
findCandidateAdvisors由BeanFactoryAdvisorRetrievalHelper幫助類執行,原理就是從BeanFactory及其全部父級BeanFactory中尋找類型爲Advisor的類,並執行getBean實例化。
public List<Advisor> findAdvisorBeans() { // Determine list of advisor bean names, if not cached already. String[] advisorNames = null; synchronized (this) { advisorNames = this.cachedAdvisorBeanNames; if (advisorNames == null) { // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the auto-proxy creator apply to them! // 尋找Advisor類型的bean advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false); this.cachedAdvisorBeanNames = advisorNames; } } if (advisorNames.length == 0) { return new LinkedList<Advisor>(); } List<Advisor> advisors = new LinkedList<Advisor>(); for (String name : advisorNames) { if (isEligibleBean(name)) { if (this.beanFactory.isCurrentlyInCreation(name)) { if (logger.isDebugEnabled()) { logger.debug("Skipping currently created advisor '" + name + "'"); } } else { try { // getBean實例化 advisors.add(this.beanFactory.getBean(name, Advisor.class)); } catch (BeanCreationException ex) { Throwable rootCause = ex.getMostSpecificCause(); if (rootCause instanceof BeanCurrentlyInCreationException) { BeanCreationException bce = (BeanCreationException) rootCause; if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) { if (logger.isDebugEnabled()) { logger.debug("Skipping advisor '" + name + "' with dependency on currently created bean: " + ex.getMessage()); } // Ignore: indicates a reference back to the bean we're trying to advise. // We want to find advisors other than the currently created bean itself. continue; } } throw ex; } } } } return advisors; }
findAdvisorsThatCanApply篩選Advisor是由AopUtils類實現。對不一樣類型的Advisor進行不一樣的處理,如IntroductionAdvisor和PointcutAdvisor。
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List<Advisor> eligibleAdvisors = new LinkedList<Advisor>(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor) { // already processed continue; } // 匹配Advisor是否適用當前bean if (canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }
其中canApply方法執行實際的匹配操做,細節部分主要是對切入點Pointcut和bean的匹配,有興趣的能夠本身深刻研究其匹配過程。
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) { if (advisor instanceof IntroductionAdvisor) { return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); } else if (advisor instanceof PointcutAdvisor) { PointcutAdvisor pca = (PointcutAdvisor) advisor; return canApply(pca.getPointcut(), targetClass, hasIntroductions); } else { // It doesn't have a pointcut so we assume it applies. return true; } }
至此也就完成了bean適用的Advisor切面的自動發現與篩選,最後由ProxyFactory完成代理建立。
在看自動代理源碼的過程當中,忽然注意到SmartInstantiationAwareBeanPostProcessor接口中的getEarlyBeanReference方法,它是Spring處理循環依賴時返回**未建立完(只實例化未作依賴注入)**Bean的擴展。關於循環依賴能夠去Bean的循環依賴一章去詳細瞭解,這裏只作簡單的說明。
有兩個單例Bean,A和B,A中引用了B,B中引用了A。Spring對這種相互依賴作了特殊的處理,即在對象實例化後緩存一份key爲beanName的ObjectFactory,ObjectFactory中的getObject方法返回當前建立對象的引用。
// 支持單例依賴循環 if (earlySingletonExposure) { // 添加Early對象緩存 addSingletonFactory(beanName, new ObjectFactory<Object>() { [@Override](https://my.oschina.net/u/1162528) public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } }); }
這裏假設先建立A對象實例,當A進行依賴注入時,須要B對象,則會經過getBean方法建立B對象。此時A並無建立完成,但在Early緩存中存有A的引用,於是當B對象進行依賴注入A時,直接返回A對象的Early引用,從而不會形成陷入無休止的依賴注入循環中。
在getEarlyBeanReference方法中,不只只是返回對象引用,還有一個擴展點,支持SmartInstantiationAwareBeanPostProcessor接口中的getEarlyBeanReference方法對返回的對象引用進行修改。
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { Object exposedObject = bean; if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; // 擴展點,對Early對象進行修改 exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); if (exposedObject == null) { return exposedObject; } } } } return exposedObject; }
回到AOP的自動代理上,在AbstractAutoProxyCreator中實現了getEarlyBeanReference擴展
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { this.earlyProxyReferences.add(cacheKey); } return wrapIfNecessary(bean, beanName, cacheKey); }
這裏將標識惟一bean的cacheKey添加到earlyProxyReferences中,在以後bean的初始化中將頗有用。而後執行wrapIfNecessary返回bean的代理對象,於是若是存在循環依賴,則依賴注入的就是真正的代理對象。
在對象執行完依賴注入後,進行初始化操做,會調用初始化後擴展postProcessAfterInitialization方法,再來關注下AbstractAutoProxyCreator此方法的實現。
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); // 判斷early引用中是否包含cacheKey if (!this.earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
它判斷了earlyProxyReferences中不包含當前bean的cacheKey纔會執行代理操做,也就是說,若是存在循環依賴時,代理對象在getEarlyBeanReference時就建立了,而在初始化後直接跳過了,返回的bean是原始的對象。
你可能會問,既然這裏返回的不是代理對象,那代理對象最後是怎樣返回的呢?
Spring在對象進行初始化後,對存在循環依賴的又作了巧妙的處理。
if (earlySingletonExposure) { // 若是存在循環依賴,則返回的爲代理對象 Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { // 循環依賴下,通過初始化後的對象同原始對象一致 // 於是將代理對象賦給最終返回的對象引用 if (exposedObject == bean) { exposedObject = earlySingletonReference; } } }
這裏的設計非常巧妙,須要結合依賴循環的處理,AOP對象的處理統一來理解。同時對循環依賴時,不直接緩存對象,而是經過ObjectFactory的方式有了更深的理解。有興趣的同窗能夠反覆琢磨一下。
2017/12/24更新
回頭再看這個循環依賴的點,仍是花了一點時間來回翻了下源碼才理解,所以再補充記錄下。getSingleton(beanName, false)方法,當不存在循環依賴時,會返回null,而存在循環依賴時,返回的是ObjectFactory的getEarlyBeanReference方法返回的對象。原始的bean對象通過getEarlyBeanReference方法後,可能存在SmartInstantiationAwareBeanPostProcessor處理器,在其getEarlyBeanReference方法中被改變了,好比AbstractAutoProxyCreator中會返回代理對象。而在AbstractAutoProxyCreator的實現中,使用cacheKey保證了生成的代理對象是單例的。所以當if (exposedObject == bean)判斷時會返回true,從而getBean方法返回的對象就是真正的代理對象。此時還有一個疑問,代理對象並無進行屬性的依賴注入以及init-method等的初始化啊?其實代理對象沒有必要去複製原始對象的內部結構,由於它持有原始對象的引用,而且實際調用方法是交由原始對象去處理的。
Spring AOP的自動代理,它同ProxyFactoryBean採用了不一樣的擴展方式。FactoryBean的擴展思路很是清晰,在工廠ProxyFactoryBean建立完成後直接根據其配置動態生成不一樣的代理對象,適用於簡單的配置,但在ApplicationContext高級容器中,就須要經過BeanPostProcessor擴展進行更細粒度的操做,從而支持複雜的業務配置。而接下來要討論的AspectJ整合Spring的基礎實現,就來自於Spring AOP的自動代理。