Spring源碼------DI依賴注入源碼分析

Spring源碼------DI依賴注入源碼分析

目錄

Spring源碼------DI依賴注入源碼分析

1、什麼是依賴注入DI

2、依賴注入時序圖

3、源碼跟蹤(簡約版)

4、總結


1、什麼是依賴注入DI

DI—Dependency Injection,即“依賴注入”組件之間依賴關係由容器在運行期決定,形象的說,即由容器動態的將某個依賴關係注入到組件之中依賴注入的目的並非爲軟件系統帶來更多功能,而是爲了提升組件重用的頻率,併爲系統搭建一個靈活、可擴展的平臺。通過依賴注入機制,我們只需要通過簡單的配置,而無需任何代碼就可指定目標需要的資源,完成自身的業務邏輯,而不需要關心具體的資源來自何處,由誰實現。

  理解DI的關鍵是:“誰依賴誰,爲什麼需要依賴,誰注入誰,注入了什麼”,那我們來深入分析一下:

  ●誰依賴於誰:當然是應用程序依賴於IoC容器

  ●爲什麼需要依賴:應用程序需要IoC容器來提供對象需要的外部資源

  ●誰注入誰:很明顯是IoC容器注入應用程序某個對象,應用程序依賴的對象

  ●注入了什麼:就是注入某個對象所需要的外部資源(包括對象、資源、常量數據)

  IoC和DI由什麼關係呢?其實它們是同一個概念的不同角度描述,由於控制反轉概念比較含糊(可能只是理解爲容器控制對象這一個層面,很難讓人想到誰來維護對象關係),所以2004年大師級人物Martin Fowler又給出了一個新的名字:“依賴注入”,相對IoC 而言,依賴注入”明確描述了“被注入對象依賴IoC容器配置依賴對象”。

通俗易懂的理解:

IoC的一個重點是在系統運行中,動態的向某個對象提供它所需要的其他對象。這一點是通過DI(Dependency Injection,依賴注入)來實現的。比如對象A需要操作數據庫,以前我們總是要在A中自己編寫代碼來獲得一個Connection對象,有了 spring我們就只需要告訴spring,A中需要一個Connection,至於這個Connection怎麼構造,何時構造,A不需要知道。在系統運行時,spring會在適當的時候製造一個Connection,然後像打針一樣,注射到A當中,這樣就完成了對各個對象之間關係的控制。A需要依賴 Connection才能正常運行,而這個Connection是由spring注入到A中的,依賴注入的名字就這麼來的。那麼DI是如何實現的呢? Java 1.3之後一個重要特徵是反射(reflection),它允許程序在運行的時候動態的生成對象、執行對象的方法、改變對象的屬性,spring就是通過反射來實現注入的。

  理解了IoC和DI的概念後,一切都將變得簡單明瞭,剩下的工作只是在spring的框架中堆積木而已。

2、依賴注入時序圖

springDI時序圖.png

3、源碼跟蹤(簡約版)

ApplicationContext上下文找getBean()

ApplicationContext裏面並沒有找到getBean(),需要在他的父類找,能找到BeanFactory

//根據bean的名字,獲取在IOC容器中得到bean實例
	Object getBean(String name) throws BeansException;

在getBean():按住Ctrl+Alt+B選擇AbstractBeanFactory,會進入AbstractBeanFactory的getBean()

	//獲取IOC容器中指定名稱的Bean
	@Override
	public Object getBean(String name) throws BeansException {
		//doGetBean纔是真正向IoC容器獲取被管理Bean的過程
		return doGetBean(name, null, null, false);
	}

在doGetBean按住Ctrl+鼠標左鍵進入doGetBean裏

//真正實現向IOC容器獲取Bean的功能,也是觸發依賴注入功能的地方
	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

	//只留主線
	//省略了走單例、走緩存
				//IOC容器創建原型模式Bean實例對象
				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					//原型模式(Prototype)是每次都會創建一個新的對象
					Object prototypeInstance = null;
					try {
						//回調beforePrototypeCreation方法,默認的功能是註冊當前創建的原型對象
						beforePrototypeCreation(beanName);
						//創建指定Bean對象實例
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						//回調afterPrototypeCreation方法,默認的功能告訴IOC容器指定Bean的原型對象不再創建
						afterPrototypeCreation(beanName);
					}
					//獲取給定Bean的實例對象
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}
		return (T) bean;
	}

在createBean()上按住Ctrl+Alt+B將從AbstractBeanFactory進入AbstractAutowireCapableBeanFactory的createBean方法

//創建Bean實例對象
	@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		//去掉了上面的其他判斷
		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			//如果Bean配置了初始化前和初始化後的處理器,則試圖返回一個需要創建Bean的代理對象
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
			//創建Bean的入口
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isDebugEnabled()) {
				logger.debug("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		//去掉了下面的catch塊。
	}

在doCreateBean()上按住Ctrl+鼠標左鍵進入自身方法


//真正創建Bean的方法
	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		//封裝被創建的Bean對象
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = instanceWrapper.getWrappedInstance();
		//獲取實例化對象的類型
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// Allow post-processors to modify the merged bean definition.
		//調用PostProcessor後置處理器
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		//向容器中緩存單例模式的Bean對象,以防循環引用
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			//這裏是一個匿名內部類,爲了防止循環引用,儘早持有對象的引用
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		//Bean對象的初始化,依賴注入在此觸發
		//這個exposedObject在初始化完成之後返回作爲依賴注入完成後的Bean
		Object exposedObject = bean;
		try {
			//將Bean實例對象封裝,並且Bean定義中配置的屬性值賦值給實例對象
			populateBean(beanName, mbd, instanceWrapper);
			//初始化Bean對象
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		//去掉了catch塊

		if (earlySingletonExposure) {
			//獲取指定名稱的已註冊的單例模式Bean對象
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				//根據名稱獲取的已註冊的Bean和正在實例化的Bean是同一個
				if (exposedObject == bean) {
					//當前實例化的Bean初始化完成
					exposedObject = earlySingletonReference;
				}
				//當前Bean依賴其他Bean,並且當發生循環引用時不允許新創建實例對象
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					//獲取當前Bean所依賴的其他Bean
					for (String dependentBean : dependentBeans) {
						//對依賴Bean進行類型檢查
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					
					//去掉了if
				}
			}
		}

		// Register bean as disposable.
		//註冊完成依賴注入的Bean
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

在這裏,doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
有兩個方法
一個是創建Bean:createBeanInstance(),創建的是一個BeanWrapper,前置條件是傳入beanName和BeanDefinition,
另一個是給Bean賦值:populateBean();
在createBeanInstance()按住Ctrl+鼠標左鍵進入createBeanInstance()方法

//創建Bean的實例對象
	protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// Make sure bean class is actually resolved at this point.
		//檢查確認Bean是可實例化的
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		//使用工廠方法對Bean進行實例化
		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
		}

		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}

		if (mbd.getFactoryMethodName() != null)  {
			//調用工廠方法實例化
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		//使用容器的自動裝配方法進行實例化
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		if (resolved) {
			if (autowireNecessary) {
				//配置了自動裝配屬性,使用容器的自動裝配實例化
				//容器的自動裝配是根據參數類型匹配Bean的構造方法
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				//使用默認的無參構造方法實例化
				return instantiateBean(beanName, mbd);
			}
		}

		// Need to determine the constructor...
		//使用Bean的構造方法進行實例化
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
			//使用容器的自動裝配特性,調用匹配的構造方法實例化
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// No special handling: simply use no-arg constructor.
		//使用默認的無參構造方法實例化
		return instantiateBean(beanName, mbd);
	}

在instantiateBean()按住Ctrl+鼠標左鍵進入instantiateBean()方法

//使用默認的無參構造方法實例化Bean對象
	protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
		try {
			Object beanInstance;
			final BeanFactory parent = this;
			//獲取系統的安全管理接口,JDK標準的安全管理API
			if (System.getSecurityManager() != null) {
				//這裏是一個匿名內置類,根據實例化策略創建實例對象
				beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
						getInstantiationStrategy().instantiate(mbd, beanName, parent),
						getAccessControlContext());
			}
			else {
				//將實例化的對象封裝起來
				beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
			}
			BeanWrapper bw = new BeanWrapperImpl(beanInstance);
			initBeanWrapper(bw);
			return bw;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
		}
	}

這裏實例化beanInstance時,用到了策略模式
在instantiate()按住Ctrl+Alt+B進入SimpleInstantiationStrategy的instantiate()方法


//使用初始化策略實例化Bean對象
	@Override
	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
		// Don't override the class with CGLIB if no overrides.
		//如果Bean定義中沒有方法覆蓋,則就不需要CGLIB父類類的方法
		if (!bd.hasMethodOverrides()) {
			Constructor<?> constructorToUse;
			synchronized (bd.constructorArgumentLock) {
				//獲取對象的構造方法或工廠方法
				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
				//如果沒有構造方法且沒有工廠方法
				if (constructorToUse == null) {
					//使用JDK的反射機制,判斷要實例化的Bean是否是接口
					final Class<?> clazz = bd.getBeanClass();
					if (clazz.isInterface()) {
						throw new BeanInstantiationException(clazz, "Specified class is an interface");
					}
					try {
						if (System.getSecurityManager() != null) {
							//這裏是一個匿名內置類,使用反射機制獲取Bean的構造方法
							constructorToUse = AccessController.doPrivileged(
									(PrivilegedExceptionAction<Constructor<?>>) () -> clazz.getDeclaredConstructor());
						}
						else {
							constructorToUse =	clazz.getDeclaredConstructor();
						}
						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
					}
					catch (Throwable ex) {
						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
					}
				}
			}
			//使用BeanUtils實例化,通過反射機制調用”構造方法.newInstance(arg)”來進行實例化
			return BeanUtils.instantiateClass(constructorToUse);
		}
		else {
			// Must generate CGLIB subclass.
			//使用CGLIB來實例化對象
			return instantiateWithMethodInjection(bd, beanName, owner);
		}
	}

最終通過反射機制調用”構造方法.newInstance(arg)”來進行實例化。
Ctrl+alt+鼠標左鍵 返回到doCreateBean()中,進入賦值階段populateBean()方法

populateBean(beanName, mbd, instanceWrapper);

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
        // 所有的屬性
    PropertyValues pvs = mbd.getPropertyValues();
    // 這裏是處理自動裝配類型的, autowire=byName 或者byType。如果不配置不走這個分支,xml或註解都可配 
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
            mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
        pvs = newPvs;
    }
    // 後處理器是否已經準備好(後處理器會處理已@Autowired 形式來注入的bean, 有一個  
    // 子類AutowiredAnnotationBeanPostProcessor來處理@Autowired注入的bean)
    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    // 是否需要依賴檢查
    boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
    if (hasInstAwareBpps || needsDepCheck) {
        PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        if (hasInstAwareBpps) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                    // 這裏會處理對註解形式的注入 重點!!!!
                    pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvs == null) {
                        return;
                    }
                }
            }
        }
    }
    // 注入參數的方法(註解的Bean的依賴注入除外)
    applyPropertyValues(beanName, mbd, bw, pvs);
}

1、這裏關注一下註解注入:

// 後處理器是否已經準備好(後處理器會處理已@Autowired 形式來注入的bean, 有一個  
// 子類AutowiredAnnotationBeanPostProcessor來處理@Autowired注入的bean)
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否需要依賴檢查
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
    PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    if (hasInstAwareBpps) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                // 這裏會處理對註解形式的注入,比如 @Autowired註解 由類AutowiredAnnotationBeanPostProcessor來處理
                pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                if (pvs == null) {
                    return;
                }
            }
        }
    }
}

pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        // 這裏定義了把誰注入到哪裏
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    try {  
       // 進行注入
       metadata.inject(bean, beanName, pvs);
    }catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
    }
    return pvs;
}

InjectionMetadata在這個類裏頭封裝了依賴的bean與被依賴的bean的信息,比如orderCcontroller 依賴orderService,需要把orderService 注入到orderController。

其中injectedElements就是所有需要被注入的bean

protected void inject(Object target, String requestingBeanName, PropertyValues pvs) throws Throwable {
    if (this.isField) {
        Field field = (Field) this.member;
        ReflectionUtils.makeAccessible(field);
        field.set(target, getResourceToInject(target, requestingBeanName));
    }else {
        if (checkPropertySkipping(pvs)) {
           return;
        }
        try {
           Method method = (Method) this.member;
           ReflectionUtils.makeAccessible(method);
           method.invoke(target, getResourceToInject(target, requestingBeanName));
        }catch (InvocationTargetException ex) {
          throw ex.getTargetException();
        }
    }
}

2.接下來就是 xml 配置形式注入的源碼

在applyPropertyValues()按住Ctrl+Alt+B進入自身的applyPropertyValues()方法

protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
		if (pvs.isEmpty()) {
			return;
		}

		//封裝屬性值
		MutablePropertyValues mpvs = null;
		List<PropertyValue> original;

		if (System.getSecurityManager() != null) {
			if (bw instanceof BeanWrapperImpl) {
				//設置安全上下文,JDK安全機制
				((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
			}
		}

		if (pvs instanceof MutablePropertyValues) {
			mpvs = (MutablePropertyValues) pvs;
			//屬性值已經轉換
			if (mpvs.isConverted()) {
				// Shortcut: use the pre-converted values as-is.
				try {
					//爲實例化對象設置屬性值
					bw.setPropertyValues(mpvs);
					return;
				}
				catch (BeansException ex) {
					throw new BeanCreationException(
							mbd.getResourceDescription(), beanName, "Error setting property values", ex);
				}
			}
			//獲取屬性值對象的原始類型值
			original = mpvs.getPropertyValueList();
		}
		else {
			original = Arrays.asList(pvs.getPropertyValues());
		}

		//獲取用戶自定義的類型轉換
		TypeConverter converter = getCustomTypeConverter();
		if (converter == null) {
			converter = bw;
		}
		//創建一個Bean定義屬性值解析器,將Bean定義中的屬性值解析爲Bean實例對象的實際值
		BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

		// Create a deep copy, resolving any references for values.

		//爲屬性的解析值創建一個拷貝,將拷貝的數據注入到實例對象中
		List<PropertyValue> deepCopy = new ArrayList<>(original.size());
		boolean resolveNecessary = false;
		
		//去掉了給deepCopy賦值

		// Set our (possibly massaged) deep copy.
		//進行屬性依賴注入
		try {
			bw.setPropertyValues(new MutablePropertyValues(deepCopy));
		}
		catch (BeansException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Error setting property values", ex);
		}
	}

在bw.setPropertyValues()方法按住Ctrl+Alt+B進入AbstractPropertyAccessor的setPropertyValues()方法

@Override
	public void setPropertyValues(PropertyValues pvs) throws BeansException {
		setPropertyValues(pvs, false, false);
	}
在下方的setPropertyValues()方法按住Ctrl+鼠標左鍵進入setPropertyValues()重載方法的
@Override
	public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)
			throws BeansException {

		List<PropertyAccessException> propertyAccessExceptions = null;
		List<PropertyValue> propertyValues = (pvs instanceof MutablePropertyValues ?
				((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues()));
		for (PropertyValue pv : propertyValues) {
			try {
				// This method may throw any BeansException, which won't be caught
				// here, if there is a critical failure such as no matching field.
				// We can attempt to deal only with less serious exceptions.
				setPropertyValue(pv);
			}
			//去掉了catch塊
		}

		// If we encountered individual exceptions, throw the composite exception.
		if (propertyAccessExceptions != null) {
			PropertyAccessException[] paeArray =
					propertyAccessExceptions.toArray(new PropertyAccessException[propertyAccessExceptions.size()]);
			throw new PropertyBatchUpdateException(paeArray);
		}
	}

在setPropertyValue()方法按住Ctrl+Alt+B選擇AbstractNestablePropertyAccessor進入AbstractNestablePropertyAccessor的setPropertyValues()方法

@Override
	public void setPropertyValue(PropertyValue pv) throws BeansException {
		PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens;
		if (tokens == null) {
			String propertyName = pv.getName();
			AbstractNestablePropertyAccessor nestedPa;
			try {
				nestedPa = getPropertyAccessorForPropertyPath(propertyName);
			}
			catch (NotReadablePropertyException ex) {
				throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
						"Nested property in path '" + propertyName + "' does not exist", ex);
			}
			tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName));
			if (nestedPa == this) {
				pv.getOriginalPropertyValue().resolvedTokens = tokens;
			}
			nestedPa.setPropertyValue(tokens, pv);
		}
		else {
			setPropertyValue(tokens, pv);
		}
	}

在setPropertyValue()方法,按住Ctrl+Alt+B進入setPropertyValue()方法

//實現屬性依賴注入功能
	protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
		if (tokens.keys != null) {
			processKeyedProperty(tokens, pv);
		}
		else {
			processLocalProperty(tokens, pv);
		}
	}
private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) {
		PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
		 
		//去掉了if		

		Object oldValue = null;
		try {
			Object originalValue = pv.getValue();
			Object valueToApply = originalValue;
			if (!Boolean.FALSE.equals(pv.conversionNecessary)) {
				if (pv.isConverted()) {
					valueToApply = pv.getConvertedValue();
				}
				else {
					if (isExtractOldValueForEditor() && ph.isReadable()) {
						try {
							oldValue = ph.getValue();
						}
						catch (Exception ex) {
							if (ex instanceof PrivilegedActionException) {
								ex = ((PrivilegedActionException) ex).getException();
							}
							if (logger.isDebugEnabled()) {
								logger.debug("Could not read previous value of property '" +
										this.nestedPath + tokens.canonicalName + "'", ex);
							}
						}
					}
					valueToApply = convertForProperty(
							tokens.canonicalName, oldValue, originalValue, ph.toTypeDescriptor());
				}
				pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
			}
			ph.setValue(valueToApply);
		}
		//去掉了catch 塊
	}

在ph.setValue()方法,按住Ctrl+Alt+B選中BeanWrapperImpl進入BeanWrapperImpl的setValue()方法

@Override
		public void setValue(final @Nullable Object value) throws Exception {
			final Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
					((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
					this.pd.getWriteMethod());
			if (System.getSecurityManager() != null) {
				AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
					ReflectionUtils.makeAccessible(writeMethod);
					return null;
				});
				try {
					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () ->
							writeMethod.invoke(getWrappedInstance(), value), acc);
				}
				catch (PrivilegedActionException ex) {
					throw ex.getException();
				}
			}
			else {
				ReflectionUtils.makeAccessible(writeMethod);
				writeMethod.invoke(getWrappedInstance(), value);
			}
		}

4、總結

Spring 如何解決循環依賴的?

Spring的單例對象的初始化主要分爲三步:

​ 1,createBeanInstance:實例化,其實也就是調用對象的構造方法實例化對象

​ 2,populateBean:填充屬性,這一步主要是多bean的依賴屬性進行填充

​ 3,initializeBean:調用spring xml中的init方法。

​ 從上可知,循環依賴主要發生在第一、第二步。也就是構造器循環依賴和field循環依賴。那麼要解決循環引用也應該從初始化過程着手,對於單例來說,在Spring容器整個生命週期內,有且只有一個對象,所以很容易想到這個對象應該存在Cache中,Spring爲了解決單例的循環依賴問題,使用了三級緩存。

​ 這三級緩存分別指:

singletonFactories :單例對象工廠的cache(解決問題的重點)

​ earlySingletonObjects :提前暴光的單例對象的Cache

​ singletonObjects:單例對象的Cache

​ Spring首先從一級緩存singletonObjects中獲取。如果獲取不到,並且對象正在創建中,就再從二級緩存中獲取。如果還是獲取不到就從三級緩存三級緩存獲取,如果獲取到了則,從三級緩存中移除,並放入二級緩存中。

​ Spring解決循環依賴的訣竅就在於singletonFactories這個三級cache。這個cache的類型是ObjectFactory。

	//向容器中緩存單例模式的Bean對象,以防循環引用
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			//這裏是一個匿名內部類,爲了防止循環引用,儘早持有對象的引用
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}


	protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {
			if (!this.singletonObjects.containsKey(beanName)) {
				this.singletonFactories.put(beanName, singletonFactory);
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
	}

// Initialize the bean instance.
		//Bean對象的初始化,依賴注入在此觸發
		//這個exposedObject在初始化完成之後返回作爲依賴注入完成後的Bean
		Object exposedObject = bean;
		try {
			//將Bean實例對象封裝,並且Bean定義中配置的屬性值賦值給實例對象
			populateBean(beanName, mbd, instanceWrapper);
			//初始化Bean對象
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

​ 這裏就是解決循環依賴的關鍵,這段代碼發生在createBeanInstance之後,也就是說單例對象此時已經被創建出來(調用了構造器)。這個對象已經被生產出來了,雖然還不完美(還沒有進行初始化的第二步和第三步),但是已經能被人認出來了(根據對象引用能定位到堆中的對象),所以Spring此時將這個對象提前曝光出來讓大家認識,讓大家使用。

​ 這樣做有什麼好處呢?

​ 例如當“A的某個field或者setter依賴了B的實例對象,同時B的某個field或者setter依賴了A的實例對象”這種循環依賴的情況。A首先完成了初始化的第一步,並且將自己提前曝光到三級緩存中,此時進行初始化的第二步,發現自己依賴對象B,此時就嘗試去get(B),發現B還沒有被create,所以走create流程,B在初始化第一步的時候發現自己依賴了對象A,於是嘗試get(A),嘗試一級緩存(肯定沒有,因爲A還沒初始化完全),嘗試二級緩存(也沒有),嘗試三級緩存由於A通過ObjectFactory將自己提前曝光了,所以B能夠通過ObjectFactory.getObject拿到A對象(雖然A還沒有初始化完全,但是總比沒有好呀),B拿到A對象後順利完成了初始化階段1、2、3,完全初始化之後將自己放入到一級緩存中。此時返回A中,A此時能拿到B的對象順利完成自己的初始化階段2、3,最終A也完成了初始化,進去了一級緩存中,而且由於B拿到了A的對象引用,所以B現在hold住的A對象完成了初始化。

​ 知道了這個原理時候,肯定就知道爲啥Spring不能解決“A的構造方法中依賴了B的實例對象,同時B的構造方法中依賴了A的實例對象”這類問題了,因爲加入三級緩存的前提是執行了構造器,所以構造器的循環依賴沒法解決。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章