Spring源碼-bean建立的核心步驟,三級緩存解決循環依賴的原理分析

BeanFactory體系

在這裏插入圖片描述
先來一張圖壓壓驚,由上圖可見DefaultListableBeanFactory爲集大成者,實現了全部接口,具有容器的基本功能,因此下文中提到的bean容器都指的是DefaultListableBeanFactory。下面對BeanFactory接口的繼承體系簡單進行介紹。

BeanFactory

bean 容器的頂級接口,該接口定義了容器提供的基本功能。java

  • ​ getBean(String beanName)--->根據名稱獲取bean
  • ​ getBean(Class classType)--->根據類型獲取bean
  • ​ isSingleton(String beanName)--->是否爲單例
  • ​ isPrototype(String beanName)--->是否爲原型
  • ​ ......

注意:此處只提供了獲取單個bean實例的功能spring

BeanFactory的直接子接口:HierarchicalBeanFactory,ListableBeanFactory,AutowireCapableBeanFactory

HierarchicalBeanFactory
具有分層能力的工廠,主要增長getParentBeanFactory()方法,所謂的父子容器
複製代碼
ListableBeanFactory
具有獲取多個bean實例功能的工廠 ,主要增長
String [] getBeanNamesForType(Class<T> classType)--->獲取bean容器中指定類型的bean名稱集合,所謂面向接口,因此可能存在多個實現類的實例
Map<String,T> getBeanOfType(Class<T> classType)--->獲取bean容器中指定類型的bean實例集合
...等相關方法
複製代碼
AutowireCapableBeanFactory
具有裝備能力的工廠,增長autowireBean(),createBean(Class<T> classType)...等相關方法
複製代碼

驚歎Spring各大繼承體系的龐大複雜之餘,初寫博客真的是一件很難的事情,仍是不繼續往下介紹了(主要是由於本身尚未徹底體會夠),因此直接擼源碼吧緩存

IOC源碼解析

前置知識:主要是爲了掃個盲,已瞭解的能夠直接略過

spring容器中一個正常的完整的單例bean的建立都要通過哪些關鍵步驟?

1.1 實例化 Instantiationbash

~Supplier接口 
正常狀況下咱們不會本身使用,都是框架內部使用的,偶然在看Mybatis源碼的時候瞥見過一眼,可參考lambda Supplier函數式接口,理解爲一個提供者
~靜態工廠方法和工廠實例方法  @Bean註解的方法會走這裏哦
~有參構造
~無參構造
主要是經過反射調用默認構造函數建立bean實例,此時bean的屬性都仍是默認值null或基本數據類型的初始值,調用有參構造函數執行過相應填充邏輯(假設有)的另當別論
複製代碼

1.2 屬性填充 Populationapp

注入屬性,所謂DI(依賴注入),@Value @Autowired @Resource等
複製代碼

1.3 初始化 Initialization框架

執行指定的初始化方法,完成自定義的初始化工做 
此處會按順序完成以下操做:
invokeAwareMethods,
postProcessBeforeInitialization,  @PreConstruct註解在此處被處理
afterPropertiesSet,   當前Bean實現InitializingBean接口時
init-method,
postProcessAfterInitialization    AOP建立代理對象的入口之一
注:@PreConstruct會被CommonAnnotationBeanPostProcessor--->InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization方法處理
複製代碼
所謂spring中的三級緩存究竟是個什麼東西?

2.1 Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256)--->一級緩存ide

​ 存放的是已經完成實例化屬性填充初始化步驟的單例bean實例函數

2.2 Map<String, Object> earlySingletonObjects = new HashMap<>(16)--->二級緩存post

​ 存放的是提早暴露的單例bean實例,多是代理對象,也多是未經代理的原對象,但都尚未完成初始化的步驟ui

2.3 Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16)--->三級緩存

​ 存放的是ObjectFactory的匿名內部類實例,一個獲取提早暴露的單例bean引用的回調getEarlyBeanReference()此處畫重點,由於能夠在這裏進行代理對象的建立,也即AOP切面的織入

事先聲明:此處僅就第一次建立單例bean的完整流程進行分析,不考慮bean已經在容器一級緩存(bean已經徹底建立好了)中的狀況

入口:AbstractBeanFactory#getBean

此抽象類實現了getBean(String beanName),內部調用doGetBean(final String name, @Nullable final Class requiredType,@Nullable final Object[] args, boolean typeCheckOnly),該方法的主要處理流程以下:

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
  Object bean; // 最終要返回的bean
	1.final String beanName transformedBeanName(name)
    2.Object sharedInstance = DefaultSingletonBeanRegistry#getSingleton(beanName); 
    	if sharedInstance != null // 不爲空,即指定beanName已完成bean的建立過程
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null)
    3.isPrototypeCurrentlyInCreation(beanName)//若是原型bean發生循環依賴則直接拋異常
    4.BeanFactory parentBeanFactory = getParentBeanFactory();
    	if parentBeanFactory != null && !containsBeanDefinition(beanName)
            //父容器不爲空且當前容器中不存在beanName對應bean定義信息時嘗試從父容器中獲取bean,又是一輪AbstractBeanFactory#getBean的調用流程,此處忽略
    5.markBeanAsCreated(beanName); //標記beanName到alreadyCreated集合中
    6.final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    7.checkMergedBeanDefinition(mbd, beanName, args);//判斷是否爲抽象類,是則直接拋異常
    8.String[] dependsOn = mbd.getDependsOn();
    	if dependsOn != null
            // 處理@DependsOn 的狀況,循環調用getBean(dep)所depends on的bean,此處忽略
    9.if (mbd.isSingleton()) {
        sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							destroySingleton(beanName);
							throw ex;
						}
					});
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    }
    10.T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType) 		           if convertedBean != null // 不爲空
        		return convertedBean;
    11. return <T> bean
  }
}
複製代碼

非重要步驟已在僞代碼中註釋,其餘重要步驟解釋以下:

  • <1>獲取原始bean名稱 此處主要完成兩個工做
    • 去掉name的前綴"&"
    • 從aliasMap中獲取bean的原始名稱 解決aliasA--->aliasB--->ABean多重別名的狀況
  • <2>嘗試從一級緩存中獲取bean實例,此處連接到DefaultSingletonBeanRegistry#getSingleton(beanName)
  • <4>父容器不爲空且當前容器中不存在beanName對應bean定義信息時嘗試從父容器中獲取bean,又是一輪AbstractBeanFactory#getBean的調用流程,此處忽略
  • <6>從父類中合併BeanDefinition信息,主要處理方法覆蓋等,此處還沒有具體深刻了解
  • <9>建立bean實例,此處連接到DefaultSingletonBeanRegistry#getSingleton(beanName,objectFactory)方法,傳遞一個ObjectFactory的匿名內部類實例,經過回調getObject()方法觸發AbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, Object[] args)的執行
  • <10>判斷createBean()返回的實例sharedInstance
    • sharedInstance instanceOf FactoryBean
      • name 包含 & 前綴 直接返回FactoryBean對象 sharedInstance
      • name 不包含 & 前綴 調用sharedInstance.getObject()方法返回真正的bean
    • !(sharedInstance instanceOf FactoryBean) 直接返回 sharedInstance
  • <11>進行必要的類型轉換
DefaultSingletonBeanRegistry#getSingleton

此處從被調用的順序分別介紹一下getSingleton的三個重載方法

原始接口方法getSingleton(String beanName)
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    // 原始接口方法
    @Override
	@Nullable
	public Object getSingleton(String beanName) {
		return getSingleton(beanName, true);
	}
}
複製代碼

實現SingletonBeanRegistry接口的方法,此處內部調用重載方法一allowEarlyReference參數爲true,該方法在AbstractBeanFactory#doCreateBean的開始地方較早的被調用

重載方法一getSingleton(String beanName, boolean allowEarlyReference)
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    // 重載方法一
    @Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// 從一級緩存中獲取單例對象
		Object singletonObject = this.singletonObjects.get(beanName);
		// isSingletonCurrentlyInCreation:判斷當前beanName是否在singletonsCurrentlyInCreation集合中
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				// 嘗試從二級緩存中獲取提早暴露的單例bean引用,getEarlyBeanReference被提早調用過期纔會存在
				singletonObject = this.earlySingletonObjects.get(beanName);
				// allowEarlyReference 是否容許從三級緩存中的ObjectFactory#getObject拿到對象
				if (singletonObject == null && allowEarlyReference) {
					// 從三級緩存中獲取
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						// 回調ObjectFactory#getObject方法獲取提早暴露的引用,也即觸發AbstractAutowireCapableBeanFactory#getEarlyBeanReference執行
						singletonObject = singletonFactory.getObject();
						// 從三級緩存移動到了二級緩存
						this.earlySingletonObjects.put(beanName, singletonObject);
                        // 同時移除三級緩存
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}  
}       
複製代碼

該重載方法主要被兩個地方調用,兩次調用所傳遞的allowEarlyReference不一樣,因此兩處調用所表明的含義也有所不一樣

  • 第一次調用:調用鏈(只列出了關鍵方法執行鏈),傳入allowEarlyReference爲true

    AbstractBeanFactory
    --->#createBean
    	--->#doCreateBean
    		--->DefaultSingletonBeanRegistry#getSingleton(beanName)
    			--->#getSingleton(beanName,true)
    複製代碼

​ 此處就是否存在循環依賴兩種狀況進行分析

  1. 不存在循環依賴:此種狀況比較簡單,由於在一開始較早的時候調用此方法,指定beanName並未出如今singletonsCurrentlyInCreation集合中,因此若是一級緩存中不存在時直接放回null

  2. 存在循環依賴:假設A->B,B->A,並先建立A 注意二者同時構造器依賴的時候,spring是沒法解決這種循環依賴的,會報錯,由於放入三級緩存的前提是Bean完成了實例化,而循環依賴的解決關鍵是三級緩存,固然二級緩存也是有它存在緣由的。

    ​ 第一次調用getBean(A)建立A,而後進入到該方法

​ 1.同一beanName A/B第一次進入此方法時直接返回null,第二次進入時則不是直接返回null了

​ 2. 進行beanName A/B 的實例化過程,實例化以前會將beanName A/B 放置到singletonsCurrentlyInCreation集合中

​ 2.1若beanName A/B 不是構造器依賴beanName B/A ,則在A/B完成實例化操做以後,此處有一個關鍵操做,會將實例化以後的bean提早暴露,經過新建ObjectFactory接口的匿名內部類實例(該實例的getObject回調方法,會觸發getEarlyBeanReference的執行,返回提早暴露的bean,Aop在此處能夠進行加強),添加進三級緩存中,而後進行屬性填充時發現依賴B/A

​ 2.2若A/B構造器依賴B/A,則在A/B實例化時發現依賴B/A, 注意此時三級緩存中並不存在提早暴露的 bean A/B,因此這種狀況下必須強制讓B/A在A/B以前調用getBean(beanName)方法,不然依舊會存在問題,不知道spring對於這種狀況會不會提早預知來調整Bean的建立順序,暫時不清楚,歡迎指點

​ 第二次調用getBean(B)建立B,重複執行以上步驟

​ 3.因此到這裏爲止,A,B分別進行了上述步驟,當第三次調用getBean(A)建立A,也即B屬性填充A時,由於A和B都執行了上述步驟,因此A,B都已經存在singletonsCurrentlyInCreation集合中,因而在1步驟並不會立馬直接返回,而是從三級緩存中獲取到了ObjectFactory接口的匿名內部類實例,並調用其getObject()方法觸發getEarlyBeanReference返回了提早暴露的bean引用,而後將引用放置到二級緩存,同時移除相應的三級緩存.

​ 4.因而B順利的完成了屬性填充及初始化工做返回,最後A也成功獲取到依賴B,完成後續的初始化工做,而後完美的解決了循環依賴的問題。

  • 第二次調用:調用鏈爲(只列出了關鍵方法執行鏈),傳入allowEarlyReference爲false

    AbstractBeanFactory
    --->createBean
    	--->doCreateBean
    --->DefaultSingletonBeanRegistry
    		--->getSingleton(beanName)
    			--->getSingleton(beanName,true)
    		--->getSingleton(beanName,objectFactory)
    			--->objectFactory.getObject()
    --->AbstractAutowireCapableBeanFactory
    			--->createBean
    				--->doCreateBean
    					--->createBeanInstance
    					--->populateBean
    					--->initializeBean
    					--->getSingleton(beanName,false)
    複製代碼

    也即在bean完成了實例化,屬性填充,初始化以後調用。若是指定的beanName存在循環依賴,並且被執行了getEarlyBeanReference將提早暴露的bean從三級緩存移到了二級緩存,那麼此處返回的bean就不爲空,後面對此處的做用作了分析。

重載方法二 getSingleton(String beanName, ObjectFactory<?> singletonFactory)
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
	// 重載方法二
    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		synchronized (this.singletonObjects) {
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				// ... 省略
                // 將當前beanName放到singletonsCurrentlyInCreation集合中
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				// ... 省略
				try {
					// 調用匿名內部類獲取單例對象,觸發AbstractAutowireCapableBeanFactory#createBean方法的執行,createBean方法的執行會完成實例化,屬性填充,初始化的工做
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
					// ... 省略
				}
				catch (BeanCreationException ex) {
					// ... 省略
				}
				finally {
					// 將當前beanName從singletonsCurrentlyInCreation集合中移除
					afterSingletonCreation(beanName);
				}
				// 將產生的單例Bean放入一級緩存中,同時移除二,三級緩存
				if (newSingleton) {
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}  
}
複製代碼

當在第一次調用原始接口方法getSingleton(String beanName)返回null時,會調用該方法,傳入一個ObjectFactory接口的匿名內部類實例,該方法主要作四件事情:

  1. 將當前beanName放到singletonsCurrentlyInCreation集合中

  2. 調用匿名內部類實例對象的getObject()方法觸發AbstractAutowireCapableBeanFactory#createBean方法的執行,createBean方法的執行會完成實例化,屬性填充,初始化的工做

  3. 將當前beanName從singletonsCurrentlyInCreation集合中移除

  4. 將產生的單例Bean放入一級緩存中,同時移除二,三級緩存

AbstractAutowireCapableBeanFactory#createBean
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
    
   	@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        RootBeanDefinition mbdToUse = mbd;
        1.Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        2.mbdToUse.prepareMethodOverrides();
        // 建立代理對象的入口之一,但此處的條件比較嚴苛,正常bean的建立流程通常不會走這裏
        3.Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
        	// 完成Bean實例的建立(實例化、填充屬性、初始化)
        4.Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        return beanInstance;
    }
}
複製代碼
AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
// AOP進行切面織入的另外一個特殊入口,要求beanName的實例已經在beanFactory中建立完成,且存在自定義的TargetSourceCreator接口的實現類
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
	Object bean = null;
	if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
		// Make sure bean class is actually resolved at this point.
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			Class<?> targetType = determineTargetType(beanName, mbd);
			if (targetType != null) {
				bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
				if (bean != null) {
					bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
				}
			}
		}
		mbd.beforeInstantiationResolved = (bean != null);
	}
	return bean;
	}
}
複製代碼
AbstractAutowireCapableBeanFactory#doCreateBean
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
 /** * 真正建立Bean的地方 * @param beanName * @param mbd * @param args * @return * @throws BeanCreationException */
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {

	// Instantiate the bean.
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	// bean初始化第一步:默認調用無參構造實例化Bean
	// 構造參數依賴注入,就是發生在這一步
	if (instanceWrapper == null) {
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	// 實例化後的Bean對象
	final Object bean = instanceWrapper.getWrappedInstance();
	Class<?> beanType = instanceWrapper.getWrappedClass();
	if (beanType != NullBean.class) {
		mbd.resolvedTargetType = beanType;
	}
	// ...
	// Eagerly cache singletons to be able to resolve circular references
	// even when triggered by lifecycle interfaces like BeanFactoryAware.
	// 解決循環依賴的關鍵步驟
	boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
			isSingletonCurrentlyInCreation(beanName));
	// 若是須要提早暴露單例Bean,則將該Bean放入三級緩存中 默認爲true
	if (earlySingletonExposure) {
		// ...
		// 將剛建立的bean放入三級緩存中singleFactories(key是beanName,value是ObjectFactory)
		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	}
	// Initialize the bean instance.
	Object exposedObject = bean;
	try {
		// bean建立第二步:填充屬性(DI依賴注入發生在此步驟)
		populateBean(beanName, mbd, instanceWrapper);
		// bean建立第三步:調用初始化方法,完成bean的初始化操做(AOP的第三個入口)
        // AOP是經過自動代理建立器AbstractAutoProxyCreator的postProcessAfterInitialization()方法的執行進行代理對象的建立的,AbstractAutoProxyCreator是BeanPostProcessor接口的實現
		exposedObject = initializeBean(beanName, exposedObject, mbd);
	}
	catch (Throwable ex) {
		// ...
	}
    // 此處要畫一個重點,我剛開始看這裏的時候忽略掉了
	if (earlySingletonExposure) {
		Object earlySingletonReference = getSingleton(beanName, false);
        // 若是從二級緩存中獲取到的經getEarlyBeanReference()處理以後的earlySingletonReference不爲空,則該earlySingletonReference可能爲代理對象,也可能爲原始對象
		if (earlySingletonReference != null) {
             // 若是完成初始化以後的bean與提早暴露的bean相等時
            // 由於在初始化時後置處理器的postProcessAfterInitialization()方法處理可能建立代理對象,也可能不建立代理對象,不建立代理對象的緣由有兩種,1.bean自己不須要被代理,2.已經在earlySingletonReference中被代理並添加到earlyProxyReferences中,此時會跳過代理直接返回原始對象
            // 此處若相等,則說明postProcessAfterInitialization中未建立代理
			if (exposedObject == bean) {
                // 無論初始化後置處理器是由於跳過代理仍是自己不須要代理,都將earlySingletonReference賦值給exposedObject
                // 跳過代理時earlySingletonReference自己就是代理對象
                // 自己不須要代理時 三者earlySingletonReference,exposedObject,bean都是原對象,不影響
                // 因此此處的關鍵點在於避免postProcessAfterInitialization()因跳過代理而致使將原始對象返回的狀況出現,因此這也就是二級緩存出現的意義,提早將可能的代理對象放置到二級緩存
				exposedObject = earlySingletonReference;
			}
			else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                // allowRawInjectionDespiteWrapping默認爲false,此時如有對象已經依賴了當前對象,好比循環依賴時從getEarlyBeanReference()提早獲取當前對象(此時的當前對象確定是原對象)進行依賴注入,由於exposedObject != bean說明postProcessAfterInitialization()返回的是代理對象
				String[] dependentBeans = getDependentBeans(beanName);
				Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
				for (String dependentBean : dependentBeans) {
                    // 若是依賴了當前對象A的對象B發現依賴的對象A是原始對象,則報錯,由於容器中真正準備放的是代理對象A @Async註解存在循環依賴且使用不當的時候可能會報這個錯誤,由於此種方式代理對象的建立是經過postProcessAfterInitialization()完成的,在getEarlyBeanReference()不會對代理對象進行建立
					if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
						actualDependentBeans.add(dependentBean);
					}
				}
				if (!actualDependentBeans.isEmpty()) {
					throw new BeanCurrentlyInCreationException(beanName,
							"Bean with name '" + beanName + "' has been injected into other beans [" +
							StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
							"] in its raw version as part of a circular reference, but has eventually been " +
							"wrapped. This means that said other beans do not use the final version of the " +
							"bean. This is often the result of over-eager type matching - consider using " +
							"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
				}
			}
		}
	}
	// ...
	return exposedObject;
   }
}
複製代碼
AbstractAutowireCapableBeanFactory#getEarlyBeanReference
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
      
    protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
   Object exposedObject = bean;
   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
         if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
            SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
             // AOP建立代理對象的第二個入口 默認由AbstractAutoProxyCreator建立
            exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
         }
      }
   }
   return exposedObject;
  }
}
複製代碼

AOP建立代理對象的三個入口

此處直接過渡到AOP的部分源碼中,窺探一眼AOP代理建立的入口方法,按照順序來,就一眼哈哈,多了頂不住

AbstractAutoProxyCreator#postProcessBeforeInstantiation
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
    @Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(beanClass, beanName);
		// 已經被通知或者已經被customTargetSourceCreators建立過期直接返回null
		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
			// 是基礎設施接口Advice.class,Pointcut.class,Advisor,AopInfrastructureBean.class的字類或者應該被跳過期直接返回null
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}
		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.
		/** * 此處要求beanFactory非空,自定義的customTargetSourceCreators(即自定義TargetSourceCreator的實現類)非空,並且beanFactory已經存在該bean時 * 因此正常建立bean的時候是不會在此處建立代理對象的 */
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
		if (targetSource != null) {
			if (StringUtils.hasLength(beanName)) {
				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;
	}
}
複製代碼
AbstractAutoProxyCreator#getEarlyBeanReference
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware { 
    @Override
	public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
		// 先獲取beanName,主要是爲FactoryBean類型添加&前綴
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		// 判斷是否已經在earlyProxyReferences集合中,不在則添加進去
		if (!this.earlyProxyReferences.contains(cacheKey)) {
			this.earlyProxyReferences.add(cacheKey);
		}
		// 建立代理對象,若是必要的話
		return wrapIfNecessary(bean, beanName, cacheKey);
	}  
    /** * Wrap the given bean if necessary, i.e. if it is eligible for being proxied. * @param bean the raw bean instance * @param beanName the name of the bean * @param cacheKey the cache key for metadata access * @return a proxy wrapping the bean, or the raw bean instance as-is */
	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		// 前面先作一些基本的判斷
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		// Advice/Pointcut/Advisor/AopInfrastructureBean接口的beanClass不進行代理以及對beanName爲aop內的切面名也不進行代理
		// 此處可查看子類複寫的shouldSkip()方法
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}
		// Create proxy if we have advice.
		// 查找對代理類相關的advisor對象集合,此處就與point-cut表達式有關了
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		// 對相應的advisor不爲空才採起代理
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			// 經過jdk動態代理或者cglib動態代理,產生代理對象,這裏傳入的是SingletonTargetSource對象喔,對原始bean對象進行了包裝
			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;
	}
}
複製代碼
AbstractAutoProxyCreator#postProcessAfterInitialization
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
    /** * Create a proxy with the configured interceptors if the bean is * identified as one to proxy by the subclass. * @see #getAdvicesAndAdvisorsForBean */
	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
		if (bean != null) {
			// 同getEarlyBeanReference開始處,解析beanName
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			// 判斷earlyProxyReferences是否已存在,若是在getEarlyBeanReference執行過代理對象的建立過程的話,則直接跳過返回原始bean對象,以防建立兩次
			if (!this.earlyProxyReferences.contains(cacheKey)) {
				// 使用動態代理技術,產生代理對象
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}
}
複製代碼

到這裏深感疲憊,還有不少東西都來不及介紹,好比BeanPostProcessor的繼承體系,好比createBeanInstance實例化bean的分析,好比populateBean依賴注入的分析,好比initializeBean初始化bean的分析,好比AOP建立代理對象的具體過程,因此給本文定一個核心就是單例bean的主要建立過程,以及循環依賴的解決過程,爲何須要三級緩存而不是二級緩存。

最後引入一個騷接口:

在這裏插入圖片描述
TargetSource是一個很騷的接口,AOP建立代理對象的時候,傳遞的是TargetSource的實現類,默認爲 SingletonTargetSource,它持有真正的target對象的引用,在AOP攔截處理過程當中,經過 SingletonTargetSource對象實例的getTargetSource()獲取真正的目標對象target,而後反射執行target目標對象的目標方法。不一樣的實現類能夠控制targe對象的返回邏輯,此處我的理解爲一種更細粒度的控制,容許開發人員介入獲取真正代理對象的過程,獲得更好的擴展。
相關文章
相關標籤/搜索