Spring
是一個開源的設計層面框架,解決了業務邏輯層和其餘各層的鬆耦合問題,將面向接口的編程思想貫穿整個系統應用,同時它也是Java工做中
必備技能之一...
<!-- more -->java
在 Spring解密 - XML解析 與 Bean註冊 中,講了 Bean的解析
,本章將詳細講解Spring中Bean的加載過程
,相比解析
而言,加載稍微複雜一點.git
public class Application { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); Person person = context.getBean("person", Person.class); System.out.println(person.toString()); } }
重點分析 context.getBean();
spring
在分析 Bean
的加載過程前,咱們看看 BeanFactory
的由來,以及 getBean
所屬的類是誰。磨刀不誤砍柴工編程
1.查看getBean()
的源碼,此處的 getBeanFactory()
是怎麼來的?緩存
public class AbstractApplicationContext{ @Override public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException { assertBeanFactoryActive(); // getBeanFactory() 是怎麼來的?咱們接着看 return getBeanFactory().getBean(name, requiredType); } }
2.應用程序的上下文微信
在 new ClassPathXmlApplicationContext("bean.xml");
中,跳轉到重載的構造方法中,咱們會發現以下代碼session
public class ClassPathXmlApplicationContext { public ClassPathXmlApplicationContext( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { super(parent); // 解析 bean.xml 文件 setConfigLocations(configLocations); if (refresh) { refresh(); } } }
它的目的是將普通路徑解析爲 類(classpath)
路徑資源名稱。多個配置文件的狀況下,後加載的 Bean
會覆蓋先前定義好的 Bean
,這樣作的目的是爲了經過額外的XML文件來特地重寫某個 Bean
。這裏咱們能夠看到調用了一個 refresh()
,它的做用是什麼呢?app
3.初始化框架
刷新容器
public class AbstractApplicationContext { @Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 準備刷新上下文 prepareRefresh(); // 通知子類,刷新內部 BeanFactory(建立 BeanFactory 的入口) ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); } } protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { // 跟蹤該方法 refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; } }
初次加載完 bean.xml
後,確定會進入到 refresh()
方法中,這個時候會作容器初始化的工做,也就是 標籤解析、Bean加載
等等工做,因爲本章重點介紹 Bean加載
,因此只貼了少許代碼(看官莫急)ide
建立
DefaultListableBeanFactory
public class AbstractRefreshableApplicationContext { @Override protected final void refreshBeanFactory() throws BeansException { // 判斷是否存在 if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { // 建立 DefaultListableBeanFactory DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { // 而後賦值給 beanFactory 變量 this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } } // 提取 BeanFactory @Override public final ConfigurableListableBeanFactory getBeanFactory() { synchronized (this.beanFactoryMonitor) { if (this.beanFactory == null) { throw new IllegalStateException("BeanFactory not initialized or already closed - " + "call 'refresh' before accessing beans via the ApplicationContext"); } return this.beanFactory; } } }
從上面的代碼塊中,咱們能夠看到 若是已經存在 beanFactory,將銷燬舊的實例,而後在建立新的 DefaultListableBeanFactory
,最後 getBeanFactory()
就能夠正常使用了。
整個 Bean
的裝載過程當中,重點圍繞 AbstractBeanFactory
,只要把它搞定剩下的就輕鬆了
public abstract class AbstractBeanFactory { @Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); } protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { // 別名轉換 final String beanName = transformedBeanName(name); Object bean; // 檢查緩存中是否存在 該 Bean 的單例(Bean默認的Scope = singleton) // 好比容器初始化的時候或者其餘地方調用過getBean,已經完成了初始化 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } // 返回實例,FactoryBean 的狀況下,並非直接返回實例自己而是返回指定方法返回的實例 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // 存在循環依賴則報錯 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // 判斷工廠中是否含有當前 Bean 的定義 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // 若是沒有,查詢父工廠 String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { // 執行帶有 args 參數的 getBean 方法 return (T) parentBeanFactory.getBean(nameToLookup, args); } else { // 若是沒有參數,執行標準的 getBean 方法 return parentBeanFactory.getBean(nameToLookup, requiredType); } } if (!typeCheckOnly) { // 若是不是作類型檢查,則須要標記此 Bean 正在建立之中 markBeanAsCreated(beanName); } try { // 將存儲XML配置文件的GernericBeanDefinition轉換成RootBeanDefinition,若是BeanName是子Bean的話會合並父類的相關屬性 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // 獲取依賴的 Bean String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep, beanName); getBean(dep); } } // 終於開始建立 Bean 實例了,若是是單例的,那麼會建立一個單例的匿名工廠, // 若是是原型模式的,則不須要建立單例的工廠的,其餘的如 request、session 做用域的,則根據自身的須要 if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args);// 調用默認構造函數,有興趣本身跟進下代碼 } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, () -> { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } }); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider " + "defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } // 類型檢查,若是不能進行類型轉換,則拋出異常 if (requiredType != null && !requiredType.isInstance(bean)) { try { T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); if (convertedBean == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return convertedBean; } catch (TypeMismatchException ex) { if (logger.isDebugEnabled()) { logger.debug("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; } }
整個代碼塊的內容仍是很多的,接下來咱們一步一步的分析。
final String beanName = transformedBeanName(name); protected String transformedBeanName(String name) { return canonicalName(BeanFactoryUtils.transformedBeanName(name)); }
去除 FactoryBean
的修飾符,最終取指定 alias
所表示的 beanName
。由於有可能獲取到以 & 開頭的 FactoryBean
,因此要進行轉化(關於 BeanFactory
和 FactoryBean
後面會進行區分)
檢查緩存中是否存在 該 Bean
的單例(Bean默認的Scope = singleton)
,如容器初始化的時候或者其餘地方已經調用過 getBean()
完成了初始化
Object sharedInstance = getSingleton(beanName);
緩存加載 Bean
默認在裝載 Bean
的時候會先去檢查 singletonObjects
是否存在,若是存在直接提取緩存的。
public class DefaultSingletonBeanRegistry { /** 保存 BeanName 和建立 bean 實例之間的關係 bean name --> bean instance */ private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); /** 保存 BeanName 和建立 bean 實例的工廠之間的關係 bean name --> ObjectFactory */ private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); /** 保存 BeanName 和建立 bean 實例之間的關係 bean name --> bean instance */ /** 與 singletonObjects 不一樣的是當一個單例 bean 被放到裏面後,那麼在 bean 在建立過程當中,就能夠經過 getBean 方法獲取到,能夠用來檢測循環引用。 **/ private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); /** 保存當前全部已註冊的 bean */ private final Set<String> registeredSingletons = new LinkedHashSet<>(256); @Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 嘗試從緩存獲取實例 Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { // 若該 bean 正在加載則不處理 singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); // 存入到緩存中 this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; } }
構建實例(無緩存狀況)
緩存中沒有,那就當場構建一個 bean
出來,能夠看到 getSingleton(String beanName, ObjectFactory<?> singletonFactory)
有兩個參數,其中的 ObjectFactory
是怎麼來的呢? 接着往下看
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { // 記錄加載狀態,,以便對循環依賴進行檢測 beforeSingletonCreation(beanName); singletonObject = singletonFactory.getObject(); // 移除加載狀態 afterSingletonCreation(beanName); addSingleton(beanName, singletonObject); } return (singletonObject != NULL_OBJECT ? singletonObject : null); } }
構建
ObjectFactory
此處與其說是構建 ObjectFactory
,不如說是在建立一個單例 Bean
if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { // 對 JDK8 lambda 表達式熟悉的小夥伴就不會陌生了 return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } }); // 劃重點了 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }
public class AbstractAutowireCapableBeanFactory { @Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; // 首先判斷須要建立的bean是否能夠被實例化,這個類是否能夠經過類裝載器來載入。 Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // 準備方法覆蓋 try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // 用 BeanPostProcessors 返回代理來替代真正的實例(若是 Bean 配置了 PostProcessor,那麼這裏返回的是一個代理) 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 { // 重點來了 Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isDebugEnabled()) { logger.debug("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException ex) { // A previously detected exception with proper bean creation context already... throw ex; } catch (ImplicitlyAppearedSingletonException ex) { // An IllegalStateException to be communicated up to DefaultSingletonBeanRegistry... throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); } } }
在建立 Bean
以前,Spring
還作了很多工做。
bean
是否能夠被實例化,這個類是否能夠經過 ClassLoader
來載入,根據設置的 class
屬性或根據 className
來解析 class
。Spring
配置中存在 lookup-mothod
和 replace-method
的,這兩個配置的加載時將配置統一存放在 BeanDefinition
中的 methodOverrides
屬性裏,這個方法的操做也是針對於這兩個配置的;bean
。在 createBean()
方法裏執行完 resolveBeforeInstantiation
方法後,若是建立了代理且不爲空的話就直接返回,不然須要進行常規 bean
的建立,這個建立過程是在 doCreateBean
中完成的上面 createBean
交給了 doCreateBean
來建立 bean
(上面還有一個重要的方法getObjectForBeanInstance,在後面分析)
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // 實例化 Bean BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { // 根據指定 bean 使用相應策略建立實例(正確狀況會調用無參構造函數) instanceWrapper = createBeanInstance(beanName, mbd, args); } // 獲取實例化好的 Bean(Person person = new Person()),此處還未進行賦值 final Object bean = instanceWrapper.getWrappedInstance(); // 得到實例化好的 class Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // 記錄建立 Bean 的 ObjectFactory,初始化前調用 post-processors,可讓咱們在 bean 實例化以前作一些定製操做 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; } } // 檢測循環依賴,是否須要提前初始化(只能解決單例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)); } // 初始化bean實例。 Object exposedObject = bean; try { // 在這個方法裏面初始化對象,配置 xml 中的各類屬性 populateBean(beanName, mbd, instanceWrapper); 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); } } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); for (String dependentBean : dependentBeans) { 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."); } } } } // 用於銷燬方法 try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }
上面源碼完成的操做能夠歸納爲如下幾點
RootBeanDefinition
是否是單例,若是是單例先移除緩存bean
,將 RootBeanDefinition
轉換爲 BeanWrapper
MergedBeanDefinitionPostProcessor
,Autowired註解
就是經過此方法實現類型的預解析;populateBean()
中填充屬性,配置在 XML
中的各類屬性DisposableBean
中Bean
的實例接下來咱們看下 Spring
是如何建立 bean
實例的。跟蹤 createBeanInstance()
方法
建立Bean實例
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // 獲取 beanClass , 要先確保 Bean 是正確的,已經解析到當前節點了 Class<?> beanClass = resolveBeanClass(mbd, beanName); 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) { // 構造方法自動注入 return autowireConstructor(beanName, mbd, null, null); } else { // 使用默認構造方法 return instantiateBean(beanName, mbd); } } // 根據參數解析構造方法 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); } // 沒有特殊處理的狀況下,只需使用無參數的構造函數。 return instantiateBean(beanName, mbd); }
能夠看出若是在 RootBeanDefinition
中存在 factoryMethodName
屬性,或者說配置文件中配置了 factory-method
,那麼 Spring
會嘗試使用 instantiateUsingFactoryMethod(beanName, mbd, args)
方法根據 RootBeanDefinition
中的配置生成bean實例。而後再解析構造方法並進行實例化,Spring
會根據參數及類型判斷使用哪一個構造方法進行實例化。判斷調用哪一個構造方法的過程會採用緩存機制,若是已經解析過則不須要重複解析而是從 RootBeanDefinition
中的屬性 resolvedConstructorOrFactoryMethod
緩存的值去取,不然需再次解析。
populateBean 屬性注入
這塊代碼比較多,有興趣請自行跟進,就不貼出來了
在 populateBean
方法的中的主要處理流程:
InstantiationAwareBeanPostProcessor
處理器的 postProcessAfterInstantiation
方法控制程序是否繼續填充屬性;bean
,並存入 PropertyValues
中;InstantiationAwareBeanPostProcessor
處理器的 postProcessPropertyValues
方法對屬性在填充前再次處理(主要仍是驗證屬性);PropertyValues
中的屬性填充到 BeanWrapper
中;initializeBean 初始化Bean
學過 Spring
的都知道 bean
配置時有一個 init-method
屬性,這個屬性的做用是在 bean
實例化前調用 init-method
指定的方法進行須要的操做,如今就進入這個方法了;Spring
執行過 bean
的實例化,而且進行屬性填充後,就會調用用戶設定的初始化方法。
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { // 特殊bean處理 invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { // 調用配置的 init-method invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
最後加載完 Bean
並執行完初始化操做後,一個 bean
的加載基本就結束了。
經過上面的描述,咱們已經知道了一個的 Bean
是如何初始化的,已經具有普通 Bean
的功能。可是 Spring
還提供了一種加強的 Bean(FactoryBean)
,具有 factory
能力的 Bean
,這個能力主要在 getObjectForBeanInstance
獲得。
public class AbstractBeanFactory { protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { // 若是想要獲取 FactoryBean 自己,那麼 beanInstance 必須是 FactoryBean 的實例 if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) { throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass()); } // 若是 instance 不是 FactoryBean 實例,或者想要獲取的就是 FactoryBean 實例,那麼直接返回就好 if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } Object object = null; if (mbd == null) { // 獲取緩存的實例 object = getCachedObjectForFactoryBean(beanName); } if (object == null) { // 緩存中沒有對象,那麼從頭準備 bean defition 實例化一個 FactoryBean<?> factory = (FactoryBean<?>) beanInstance; // Caches object obtained from FactoryBean if it is a singleton. if (mbd == null && containsBeanDefinition(beanName)) { mbd = getMergedLocalBeanDefinition(beanName); } boolean synthetic = (mbd != null && mbd.isSynthetic()); // 在這裏面得到最終的FactoryBean object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; } }
關於 BeanFactory
和 FactoryBean
的區別:
Bean
Bean
,能夠看成工廠使用的 Bean
上面有簡單提到過 循環依賴(只有在單例狀況下才會嘗試解決循環依賴)。 沒法解決就只能拋出 BeanCurrentlyInCreationException
異常
構造器循環依賴
沒法解決,只能拋出 BeanCurrentlyInCreationException
異常
<bean id="A" class="com.battcn.A"> <constructor-arg index="0" ref="B" /> </bean> <bean id="B" class="com.battcn.B"> <constructor-arg index="0" ref="C" /> </bean> <bean id="C" class="com.battcn.C"> <constructor-arg index="0" ref="A" /> </bean>
setter 循環依賴
Spring
容器提早暴露了恰好完成的構造器注入,但未完成其餘步驟 (如 setter 注入
的 bean
)。只能解決單例做用域的 bean
循環依賴。
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
prototype 範圍的依賴處理
Spring
容器沒法完成依賴注入,由於 Spring
容器不會緩存 prototype
做用域的 bean
,所以沒法提早暴露一個建立中的 bean
。
<bean id="A" class="com.battcn.A" scope="prototype"> <property name="B" ref="B" /> </bean> <bean id="B" class="com.battcn.B" scope="prototype"> <property name="C" ref="C" /> </bean> <bean id="C" class="com.battcn.C" scope="prototype"> <property name="A" ref="A" /> </bean>
熬過幾個無人知曉的秋冬春夏,撐過去一切都會順着你想要的方向走...
全文代碼:https://gitee.com/battcn/battcn-spring-source/tree/master/Chapter4
微信公衆號:battcn
(歡迎調戲)