Spring源碼------DI依賴注入源碼分析
目錄
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、依賴注入時序圖
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的實例對象”這類問題了,因爲加入三級緩存的前提是執行了構造器,所以構造器的循環依賴沒法解決。