自定義的Bean定義html
class MyBeanDefinition{ public String id; public String className; public String value; public MyBeanDefinition(String id, String className, String value) { this.id = id; this.className = className; this.value = value; } }
自定義的Bean工廠node
class MyBeanFactory { Map<String, Object> beanMap = new HashMap<>(); public MyBeanFactory(MyBeanDefinition beanDefinition) throws ClassNotFoundException, IllegalAccessException, InstantiationException { Class<?> beanClass = Class.forName(beanDefinition.className); Object bean = beanClass.newInstance(); ((UserService) bean).setName(beanDefinition.value); beanMap.put(beanDefinition.id, bean); } public Object getBean(String id) { return beanMap.get(id); } }
測試傻瓜版IOC容器spring
public class EasyIOC { public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException { MyBeanDefinition beanDefinition = new MyBeanDefinition("userService", "com.valarchie.UserService", "archie"); MyBeanFactory beanFactory = new MyBeanFactory(beanDefinition); UserService userService = (UserService) beanFactory.getBean("userService"); System.out.println(userService.getName()); } }
按照個人理解,我總結爲如下三步設計模式
因此,接下來咱們不會通盤分析整個IOC的流程,由於旁枝細節太多讀者看完也雲裏霧裏抓不到重點。
咱們經過分析最重要的這條代碼主幹線來理解IOC的過程。數組
首先咱們從xml的配置方式開始分析,由於Spring最初的配置方式就是利用xml來進行配置,因此大部分人對xml的配置形式較爲熟悉,也比較方便理解。緩存
從ClassPathXmlApplicationContext的構造器開始講起。app
public class TestSpring { public static void main(String[] args) { // IOC容器的啓動就從ClassPathXmlApplicationContext的構造方法開始 ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml"); UserService userService = (UserService) context.getBean("userService"); System.out.println(userService.getName()); } }
進入到構造方法中,調用重載的另外一個構造方法。dom
// 建立ClassPathXmlApplicationContext,加載給定的位置的xml文件,並自動刷新context public ClassPathXmlApplicationContext(String configLocation) throws BeansException { this(new String[] {configLocation}, true, null); }
重載的構造方法中,因爲剛纔parrent參數傳爲null,因此不設置父容器。refresh剛纔設置爲true,流程就會進入refresh()方法中ide
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { // 因爲以前的方法調用將parent設置爲null,因此咱們就不分析了 super(parent); // 設置路徑數組,並依次對配置路徑進行簡單佔位符替換處理,比較簡單,咱們也不進入分析了 setConfigLocations(configLocations); if (refresh) { refresh(); } }
整個refresh()方法中就是IOC容器啓動的主幹脈絡了,Spring採用了模板方法設計模式進行refresh()方法的設計,先規定好整個IOC容器的具體步驟,而後將每個小步驟由各類不一樣的子類本身實現。post
全部重要的操做都是圍繞着BeanFactory在進行。
在註釋當中,咱們詳細的列出了每一步方法所完成的事情。ApplicationContext內部持有了FactoryBean的實例。其實ApplicationContext自己最上層的父接口也是BeanFactory,他拓展了BeanFactory以外的功能(提供國際化的消息訪問、資源訪問,如URL和文件、事件傳播、載入多個(有繼承關係)上下文)
咱們先經過閱讀代碼中的註釋來了解大概的脈絡。
public void refresh() throws BeansException, IllegalStateException { // 先加鎖防止啓動、結束衝突 synchronized (this.startupShutdownMonitor) { // 在刷新以前作一些準備工做 // 設置啓動的時間、相關狀態的標誌位(活動、關閉)、初始化佔位符屬性源,並確認 // 每一個標記爲必須的屬性都是可解析的。 prepareRefresh(); // 獲取一個已刷新的BeanFactory實例。 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 定義好Bean工廠的環境特性,例如類加載器,或者後置處理器 prepareBeanFactory(beanFactory); try { // 設置在BeanFactory完成初始化以後作一些後置操做,spring留給子類的擴展。 postProcessBeanFactory(beanFactory); // 啓動以前已設置的BeanFactory後置處理器 invokeBeanFactoryPostProcessors(beanFactory); // 註冊Bean處理器 registerBeanPostProcessors(beanFactory); // 爲咱們的應用上下文設置消息源(i18n) initMessageSource(); // 初始化事件廣播器 initApplicationEventMulticaster(); // 初始化特殊的Bean在特殊的Context中,默認實現爲空,交給各個具體子類實現 onRefresh(); // 檢查監聽器並註冊 registerListeners(); // 實例化全部非懶加載的Bean finishBeanFactoryInitialization(beanFactory); // 最後一步發佈相應的事件 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // 若是啓動失敗的話,要銷燬以前建立的Beans。 destroyBeans(); // 重置ApplicationContext內部active的標誌位 cancelRefresh(ex); // 向調用者拋出異常 throw ex; } finally { // 重置Spring核心內的緩存,由於咱們可能再也不須要單例bean相關的元數據 resetCommonCaches(); } } }
閱讀完以後咱們重點關注obtainFreshBeanFactory()、finishBeanFactoryInitialization(beanFactory)這兩個方法,由於實質上整個IOC的流程都在這兩個方法當中,其餘的方法一部分是Spring預留給用戶的自定義操做如BeanFactory的後置處理器和Bean後置處理器,一部分是關鍵啓動事件的發佈和監聽操做,一部分是關於AOP的操做。
首先,先從obtainFreshBeanFactory()開始提及。
在getBeanFactory()方法以前,先調用refreshBeanFactory()方法進行刷新。咱們先說明一下,getBeanFactory()很是簡單,默認實現只是將上一步刷新成功好構建好的Bean工廠進行返回。返回出去的Bean工廠已經加載好Bean定義了。因此在refreshBeanFactory()這個方法中已經包含了第一步讀取xml文件構建DOM對象和第二步解析DOM中的元素生成Bean定義進行保存。記住,這裏僅僅是保存好Bean定義,此時並未涉及Bean的實例化。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }
進入refreshBeanFactory()方法中
protected final void refreshBeanFactory() throws BeansException { // 若是當前ApplicationContext中已存在FactoryBean的話進行銷燬 if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { // 先生成一個BeanFactory DefaultListableBeanFactory beanFactory = createBeanFactory(); // 設置序列化 beanFactory.setSerializationId(getId()); // 設置是否能夠覆蓋Bean定義和是否能夠循環依賴,具體我就不解釋了 customizeBeanFactory(beanFactory); // 加載Bean定義到Factory當中去 // 重點! loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
接下來,進入核心方法loadBeanDefinitions(beanFactory)中,參數是剛建立的beanFactory
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // 根據傳入的beanfactory建立一個xml讀取器 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // 設置bean定義讀取器的相關資源加載環境 beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // 這個方法讓子類自定義讀取器Reader的初始化 initBeanDefinitionReader(beanDefinitionReader); // 接着開始實際加載Bean定義 loadBeanDefinitions(beanDefinitionReader); }
進入loadBeanDefinitions(beanDefinitionReader)方法中,參數是剛剛建立好的Reader讀取器。
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { // 若是有已經生成好的Resouce實例的話就直接進行解析。 // 默認的實現是返回null,由子類自行實現。 Resource[] configResources = getConfigResources(); if (configResources != null) { reader.loadBeanDefinitions(configResources); } // 沒有Resouces的話就進行路徑解析。 String[] configLocations = getConfigLocations(); if (configLocations != null) { reader.loadBeanDefinitions(configLocations); } }
咱們進入reader.loadBeanDefinitions(configLocations)方法中,這裏面方法調用有點繞,我這邊只簡單地描述一下
該方法會根據多個不一樣位置的xml文件依次進行處理。
接着會對路徑的不一樣寫法進行不一樣處理,例如classpath或者WEB-INF的前綴路徑。
根據傳入的locations變量生成對應的Resouces。
緊接着進入reader.loadBeanDefinitions(resource)此時參數是Resource。
在通過一層進入loadBeanDefinitions(new EncodedResource(resource))的方法調用中。
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { Assert.notNull(encodedResource, "EncodedResource must not be null"); if (logger.isInfoEnabled()) { logger.info("Loading XML bean definitions from " + encodedResource.getResource()); } // 經過ThreadLocal實現的當前currentResource Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get(); if (currentResources == null) { currentResources = new HashSet<EncodedResource>(4); this.resourcesCurrentlyBeingLoaded.set(currentResources); } if (!currentResources.add(encodedResource)) { throw new BeanDefinitionStoreException( "Detected cyclic loading of " + encodedResource + " - check your import definitions!"); } try { // 最主要的方法在這段 InputStream inputStream = encodedResource.getResource().getInputStream(); try { // 傳入流對象,並設置好編碼 InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); } return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); } finally { inputStream.close(); } } catch (IOException ex) { throw new BeanDefinitionStoreException( "IOException parsing XML document from " + encodedResource.getResource(), ex); } finally { currentResources.remove(encodedResource); if (currentResources.isEmpty()) { this.resourcesCurrentlyBeingLoaded.remove(); } } }
該方法最主要是建立了對應的輸入流,並設置好編碼。
而後開始調用doLoadBeanDefinitions()方法。
// 內部核心代碼就這兩句 Document doc = doLoadDocument(inputSource, resource); return registerBeanDefinitions(doc, resource);
在loadDocument()方法中會生成一個DocumentBuilderImpl對象,這個對象會調用parse方法,在parse方法中使用SAX進行解析剛纔的輸入流包裝的InputSource,生成DOM對象返回。
public Document parse(InputSource is) throws SAXException, IOException { if (is == null) { throw new IllegalArgumentException( DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "jaxp-null-input-source", null)); } if (fSchemaValidator != null) { if (fSchemaValidationManager != null) { fSchemaValidationManager.reset(); fUnparsedEntityHandler.reset(); } resetSchemaValidator(); } // 解析xml domParser.parse(is); // 獲取剛纔解析好的dom Document doc = domParser.getDocument(); domParser.dropDocumentReferences(); return doc; }
// 內部核心代碼就這兩句 Document doc = doLoadDocument(inputSource, resource); return registerBeanDefinitions(doc, resource);
咱們再回到剛剛講到的這兩句核心代碼,第一句獲取DOM對象後,緊接着第二句registerBeanDefinitions(doc, resource)開始了bean定義的註冊工做。
進入registerBeanDefinitions(doc, resource)方法中
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { // 生成DOM讀取器,這個和剛纔的讀取器不同,以前的讀取器是xml讀取器。 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); // 獲取以前的bean定義數量 int countBefore = getRegistry().getBeanDefinitionCount(); // 進入重點 documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); // 用剛剛又建立的bean定義數量 - 以前的bean定義數量 = 剛剛一共建立的bean定義 return getRegistry().getBeanDefinitionCount() - countBefore; }
進入documentReader.registerBeanDefinitions(doc, createReaderContext(resource))方法。
方法內讀取文檔的root元素。
protected void doRegisterBeanDefinitions(Element root) { // Any nested <beans> elements will cause recursion in this method. In // order to propagate and preserve <beans> default-* attributes correctly, // keep track of the current (parent) delegate, which may be null. Create // the new (child) delegate with a reference to the parent for fallback purposes, // then ultimately reset this.delegate back to its original (parent) reference. // this behavior emulates a stack of delegates without actually necessitating one. BeanDefinitionParserDelegate parent = this.delegate; // 生成Bean定義解析類 this.delegate = createDelegate(getReaderContext(), root, parent); // 若是是xml文檔中的namespace,進行相應處理 if (this.delegate.isDefaultNamespace(root)) { String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { String[] specifiedProfiles = StringUtils.tokenizeToStringArray( profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { if (logger.isInfoEnabled()) { logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + getReaderContext().getResource()); } return; } } } // spring預留給子類的拓展性方法 preProcessXml(root); // 重點 // 開始解析Bean定義 parseBeanDefinitions(root, this.delegate); // spring預留給子類的拓展性方法 postProcessXml(root); this.delegate = parent; }
進入parseBeanDefinitions(root, this.delegate)。將以前的文檔對象和bean定義解析類做爲參數傳入。
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { if (delegate.isDefaultNamespace(root)) { NodeList nl = root.getChildNodes(); // 遍歷去解析根節點的每一個子節點元素 for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); // 若是是標籤元素的話 if (node instanceof Element) { Element ele = (Element) node; if (delegate.isDefaultNamespace(ele)) { // 解析默認的元素 // 重點 parseDefaultElement(ele, delegate); } else { // 解析指定自定義元素 delegate.parseCustomElement(ele); } } } } else { // 非默認命名空間的,進行自定義解析,命名空間就是xml文檔頭內的xmlns,用來定義標籤。 delegate.parseCustomElement(root); } }
進入到parseDefaultElement(ele, delegate)當中,會發現其實對四種標籤進行分別的解析。
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { importBeanDefinitionResource(ele); } else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { processAliasRegistration(ele); } else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { // 分析Bean標籤 processBeanDefinition(ele, delegate); } else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // recurse doRegisterBeanDefinitions(ele); } }
咱們主要分析Bean元素標籤的解析,進入processBeanDefinition(ele, delegate)方法中最內層。
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { // 獲取bean標籤內的id String id = ele.getAttribute(ID_ATTRIBUTE); // 獲取bean標籤內的name String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); // 設置多別名 List<String> aliases = new ArrayList<String>(); if (StringUtils.hasLength(nameAttr)) { String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); aliases.addAll(Arrays.asList(nameArr)); } // 當沒有設置id的時候 String beanName = id; if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { beanName = aliases.remove(0); if (logger.isDebugEnabled()) { logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases"); } } // 檢查beanName是否惟一 if (containingBean == null) { checkNameUniqueness(beanName, aliases, ele); } // 內部作了Bean標籤的解析工做 AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null) { if (!StringUtils.hasText(beanName)) { try { if (containingBean != null) { beanName = BeanDefinitionReaderUtils.generateBeanName( beanDefinition, this.readerContext.getRegistry(), true); } else { beanName = this.readerContext.generateBeanName(beanDefinition); // Register an alias for the plain bean class name, if still possible, // if the generator returned the class name plus a suffix. // This is expected for Spring 1.2/2.0 backwards compatibility. String beanClassName = beanDefinition.getBeanClassName(); if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { aliases.add(beanClassName); } } if (logger.isDebugEnabled()) { logger.debug("Neither XML 'id' nor 'name' specified - " + "using generated bean name [" + beanName + "]"); } } catch (Exception ex) { error(ex.getMessage(), ele); return null; } } String[] aliasesArray = StringUtils.toStringArray(aliases); return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } return null; }
將解析好的Bean定義並附加別名數組填入new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray)中進行返回。而後調用如下這個方法。
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())
最主要的操做就是將剛纔解析好的Bean定義放入beanDefinitionMap中去。
咱們回到最開始的refresh方法中,在finishBeanFactoryInitialization(beanFactory)方法中,開始實例化非懶加載的Bean對象。咱們跟着調用鏈進入到preInstantiateSingletons()方法中
@Override public void preInstantiateSingletons() throws BeansException { if (this.logger.isDebugEnabled()) { this.logger.debug("Pre-instantiating singletons in " + this); } // 將以前作好的bean定義名列表拷貝放進beanNames中,而後開始遍歷 List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames); // 觸發全部非懶加載的單例Bean實例化 for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); // 若是非抽象而且是單例和非懶加載的話 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { // 檢測是不是工廠方法Bean。 建立Bean的不一樣方式,讀者可自行百度。 if (isFactoryBean(beanName)) { final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName); boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { @Override public Boolean run() { return ((SmartFactoryBean<?>) factory).isEagerInit(); } }, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } else { getBean(beanName); } } } // 關於實例化以後作的自定義操做代碼省略.... }
在該方法中根據Bean實例是經過工廠方法實例仍是普通實例化,最主要的方法仍是getBean(beanName)方法。咱們繼續分析普通實例化的過程。進入getBean()方法當中doGetBean()方法,發現方法參數doGetBean(name, null, null, false)後三個參數所有爲null,它就是整個IOC中的核心代碼。
代碼中先經過實例化Bean,實例化好以後再判斷該Bean所需的依賴,並遞歸調用進行實例化bean,成功後整個IOC的核心流程也就完成了。
protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); Object bean; // Eagerly check singleton cache for manually registered singletons. 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 + "'"); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // 若是當前Bean正在建立中的話就直接失敗, // 能夠陷入了循環引用。 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // 檢測Bean定義是否出如今父Bean工廠 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // 父工廠不爲null而且當前不包含這個Bean定義時 // 從父工廠去返回Bean String nameToLookup = originalBeanName(name); if (args != null) { // Delegation to parent with explicit args. return (T) parentBeanFactory.getBean(nameToLookup, args); } else { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } } // 若是不須要類型檢查的話 標記爲已建立 if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { // 將子Bean定義與父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 + "'"); } // 註冊依賴的Bean registerDependentBean(dep, beanName); try { // 遞歸調用生成所需依賴的Bean getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // 若是是單例的話 if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { 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, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { 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; } } // 檢測實例Bean的類型和所需類型是否一致 if (requiredType != null && bean != null && !requiredType.isInstance(bean)) { try { return getTypeConverter().convertIfNecessary(bean, requiredType); } 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; }
文章篇幅有限,IOC整個的建立過程仍是比較冗長的,但願讀者看完文章對IOC的建立過程有一個主幹脈絡的思路以後仍是須要翻開源碼進行解讀,其實閱讀源碼並不難,由於Spring的代碼註釋都挺健全,若是遇到不清楚的稍微google一下就知道了。建議讀者本身試着一步一步的分析IOC過程的源碼。