本篇內(nèi)容介紹了“如何理解容器Spring IOC”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!
為崇左等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計制作服務(wù),及崇左網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為成都網(wǎng)站設(shè)計、網(wǎng)站建設(shè)、崇左網(wǎng)站設(shè)計,以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(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òu)造,但是第一個構(gòu)造調(diào)用了第二個,第二個構(gòu)造只有兩步。我們繼續(xù)往下看
super(parentBeanFactory):用來初始化父類
this.reader.loadBeanDefinitions(resource):spring初始化資源加載的真正實現(xiàn)
我們先來看看“super(parentBeanFactory):用來初始化父類”這一步做了什么吧
/** * 先是調(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()無參構(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; }
到這里是不是比較明了的知道了這一步具體做了什么?其實看完super(parentBeanFactory)的源碼發(fā)現(xiàn)就做了兩件事:獲取添加需要忽略指定接口實現(xiàn)類的自動裝配和初始化。那我們的第二步具體做了什么呢?
之前我們說了我們應(yīng)該是根據(jù)配置文件找到對應(yīng)的類,那源碼是這樣嗎?看看這句代碼的實現(xiàn)就知道了。
/** * 先是調(diào)用loadBeanDefinitions(Resource resource) */ public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException { return loadBeanDefinitions(new EncodedResource(resource)); } /** * 這個方法正是我們之前推測的實現(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)我們貼完代碼之后,是不是可以明顯的看到我們之前推測的實際證據(jù)?
我們從上面的源碼看到,我們定義的類在xml中,源碼里面有InputStream。但是傳入的只有一個ClassPathResource。那他是怎么封裝進入ClassPathResource的呢?
其實這里的關(guān)聯(lián)比較簡單。我們不妨來看看這些類的類結(jié)構(gòu)圖
到這里是不是就已經(jīng)很明了了我們的InputStream是怎么將內(nèi)容傳遞進入ClassPathResource
獲取bean才是我們這一段操作的最關(guān)鍵的地方,那bean又是怎么獲取出來的呢?這里貼一下主代碼吧
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; }
僅從代碼量上就能看出來bean的加載經(jīng)歷了一個相當(dāng)復(fù)雜的過程,其中涉及各種各樣的考慮。
我們將上面的內(nèi)容大致總結(jié)一下:
轉(zhuǎn)換對應(yīng)beanName。
嘗試從緩存中加載單例。
bean的實例化。
原型模式的依賴檢查。
檢測parentBeanFactory。
將存儲XML配置文件的GernericBeanDefinition轉(zhuǎn)換為RootBeanDefinition。
尋找依賴。
針對不同的scope進行bean的創(chuàng)建。
類型轉(zhuǎn)換。(強轉(zhuǎn))
“如何理解容器Spring IOC”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!
本文標(biāo)題:如何理解容器SpringIOC
當(dāng)前URL:http://vcdvsql.cn/article44/iigihe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供軟件開發(fā)、面包屑導(dǎo)航、云服務(wù)器、Google、關(guān)鍵詞優(yōu)化、App開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)