您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“如何理解容器Spring IOC”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
/** * Create a new XmlBeanFactory with the given resource, * which must be parsable using DOM. * @param resource the XML resource to load bean definitions from * @throws BeansException in case of loading or parsing errors */ public XmlBeanFactory(Resource resource) throws BeansException { this(resource, null); } /** * Create a new XmlBeanFactory with the given input stream, * which must be parsable using DOM. * @param resource the XML resource to load bean definitions from * @param parentBeanFactory parent bean factory * @throws BeansException in case of loading or parsing errors */ public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { super(parentBeanFactory); this.reader.loadBeanDefinitions(resource); }
我們使用的就是第一個(gè)構(gòu)造,但是第一個(gè)構(gòu)造調(diào)用了第二個(gè),第二個(gè)構(gòu)造只有兩步。我們繼續(xù)往下看
super(parentBeanFactory):用來(lái)初始化父類
this.reader.loadBeanDefinitions(resource):spring初始化資源加載的真正實(shí)現(xiàn)
我們先來(lái)看看“super(parentBeanFactory):用來(lái)初始化父類”這一步做了什么吧
/** * 先是調(diào)用DefaultListableBeanFactory(@Nullable BeanFactory parentBeanFactory)帶參構(gòu)造方法 */ public DefaultListableBeanFactory(@Nullable BeanFactory parentBeanFactory) { super(parentBeanFactory); } /** * 調(diào)用父類AbstractAutowireCapableBeanFactory */ public AbstractAutowireCapableBeanFactory(@Nullable BeanFactory parentBeanFactory) { this(); setParentBeanFactory(parentBeanFactory); } /** * 調(diào)用AbstractAutowireCapableBeanFactory()無(wú)參構(gòu)造方法 */ public AbstractAutowireCapableBeanFactory() { super(); ignoreDependencyInterface(BeanNameAware.class); ignoreDependencyInterface(BeanFactoryAware.class); ignoreDependencyInterface(BeanClassLoaderAware.class); } /** * 在初始化XmlBeanFactory容器 */ public void setParentBeanFactory(@Nullable BeanFactory parentBeanFactory) { if (this.parentBeanFactory != null && this.parentBeanFactory != parentBeanFactory) { throw new IllegalStateException("Already associated with parent BeanFactory: " + this.parentBeanFactory); } this.parentBeanFactory = parentBeanFactory; }
到這里是不是比較明了的知道了這一步具體做了什么?其實(shí)看完super(parentBeanFactory)的源碼發(fā)現(xiàn)就做了兩件事:獲取添加需要忽略指定接口實(shí)現(xiàn)類的自動(dòng)裝配和初始化。那我們的第二步具體做了什么呢?
之前我們說(shuō)了我們應(yīng)該是根據(jù)配置文件找到對(duì)應(yīng)的類,那源碼是這樣嗎?看看這句代碼的實(shí)現(xiàn)就知道了。
/** * 先是調(diào)用loadBeanDefinitions(Resource resource) */ public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException { return loadBeanDefinitions(new EncodedResource(resource)); } /** * 這個(gè)方法正是我們之前推測(cè)的實(shí)現(xiàn) * 從xml配置文件中加載bean */ public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { Assert.notNull(encodedResource, "EncodedResource must not be null"); if (logger.isTraceEnabled()) { logger.trace("Loading XML bean definitions from " + encodedResource); } Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get(); if (currentResources == null) { currentResources = new HashSet<>(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(); } } }
當(dāng)我們貼完代碼之后,是不是可以明顯的看到我們之前推測(cè)的實(shí)際證據(jù)?
我們從上面的源碼看到,我們定義的類在xml中,源碼里面有InputStream。但是傳入的只有一個(gè)ClassPathResource。那他是怎么封裝進(jìn)入ClassPathResource的呢?
其實(shí)這里的關(guān)聯(lián)比較簡(jiǎn)單。我們不妨來(lái)看看這些類的類結(jié)構(gòu)圖
到這里是不是就已經(jīng)很明了了我們的InputStream是怎么將內(nèi)容傳遞進(jìn)入ClassPathResource
獲取bean才是我們這一段操作的最關(guān)鍵的地方,那bean又是怎么獲取出來(lái)的呢?這里貼一下主代碼吧
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; // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isTraceEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // Fail if we're already creating this bean instance: // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { // Delegation to parent with explicit args. return (T) parentBeanFactory.getBean(nameToLookup, args); } else if (requiredType != null) { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } else { return (T) parentBeanFactory.getBean(nameToLookup); } } if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. 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); try { getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // Create bean instance. 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; } } // Check if required type matches the type of the actual bean instance. 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.isTraceEnabled()) { logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }
僅從代碼量上就能看出來(lái)bean的加載經(jīng)歷了一個(gè)相當(dāng)復(fù)雜的過(guò)程,其中涉及各種各樣的考慮。
我們將上面的內(nèi)容大致總結(jié)一下:
轉(zhuǎn)換對(duì)應(yīng)beanName。
嘗試從緩存中加載單例。
bean的實(shí)例化。
原型模式的依賴檢查。
檢測(cè)parentBeanFactory。
將存儲(chǔ)XML配置文件的GernericBeanDefinition轉(zhuǎn)換為RootBeanDefinition。
尋找依賴。
針對(duì)不同的scope進(jìn)行bean的創(chuàng)建。
類型轉(zhuǎn)換。(強(qiáng)轉(zhuǎn))
“如何理解容器Spring IOC”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。