日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

中getname_Spring IOC中的灵魂伴侣:BeanFactory ApplicationContext

發布時間:2024/9/19 javascript 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 中getname_Spring IOC中的灵魂伴侣:BeanFactory ApplicationContext 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

推薦閱讀:

  • 手撕分布式技術:限流、通訊、緩存,全部一鍋端走送給你
  • 秋招面試總結:Java+并發+Spring+MySQL+分布式+Redis+算法+JVM等
  • Spring全家桶筆記:Spring+Spring Boot+Spring Cloud+Spring MVC

BeanFactory & FactoryBean

說起Spring中的靈魂伴侶難道不是BeanFactory與FactoryBean嗎?ta們兩個不僅長相相似,在面試題目中更是形影不離,成雙成對。然而事實上二者的關系就像生命中的過客,只是匆匆一眼,便相忘于江湖。 不過FactoryBean并不孤單,遠處的ObjcetFactory遙遙相望,本文中并不準備詳細解析這兩個接口,不過讀者可以把他們兩個理解為指定類型Bean的孵化器,我們可以通過這兩個接口改變Bean的初始化行為。但是二者還是有很大區別的。

BeanFactory & ApplicationContext

日常工作中我們常常將BeanFactory稱為容器,而將ApplicationContext稱為上下文。不知大家究竟有沒有思考過二者之間的關系。Spring Aware接口家族一文中我曾詳細闡釋過如何獲取當前運行環境中的BeanFactory、ApplicationContext,我們不妨在代碼中找尋答案。

  • 配置類
package com.spring.container;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;@Configuration@ComponentScan("com.spring.container")public class ContainerConfig {}
  • 獲取二者信息
package com.spring.container;import org.springframework.beans.BeansException;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.BeanFactoryAware;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Component;/** * @Author: Raphael */@Componentpublic class SpringIoc implements BeanFactoryAware, ApplicationContextAware { @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.err.println(System.identityHashCode(beanFactory)); System.out.println(beanFactory.getClass().getName()); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.err.println(System.identityHashCode(applicationContext)); System.out.println(applicationContext.getClass().getName()); }}
  • 啟動類
package com.spring.container;import org.springframework.context.annotation.AnnotationConfigApplicationContext;/** * @Author: Raphael */public class MainContainer { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ContainerConfig.class); context.close(); }}
  • 結果

顯而易見二者不僅不是一個對象,類型都不一樣。看到這里大多數人的認知已經破碎,因為潛意識中他們認為二者其實是一個事物。事實上人家甚至連繼承關系都沒有,直接打碎了另一波人的幻想。不信我們看看二者的UML類圖。

幾個容器?

敏銳的人其實已經發現了矛盾,認知中Spring的根容器應該有且只有一個才合理。但是這分明就是兩個沒有什么關聯的對象啊。Spring官方文檔如此論述二者的關系:

簡而言之,BeanFactory提供了配置框架和基本功能,ApplicationContext增加了更多針對企業的功能。ApplicationContext是BeanFactory的一個完整的超集。

按照官方的解釋:二者是一個包含與被包含的關系,那么在ApplicationContext中我們可以獲得根容器嗎? 上帝說:要有光,于是getAutowireCapableBeanFactory()就來了。

package com.spring.container;import org.springframework.beans.BeansException;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.BeanFactoryAware;import org.springframework.beans.factory.config.AutowireCapableBeanFactory;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Component;/** * @Author: Raphael */@Componentpublic class SpringIoc implements BeanFactoryAware, ApplicationContextAware { private BeanFactory beanFactory; @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; System.err.println(System.identityHashCode(beanFactory)); System.out.println(beanFactory.getClass().getName()); } // 直接打印兩個對象的比對結果 @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { AutowireCapableBeanFactory factory = applicationContext.getAutowireCapableBeanFactory(); System.err.println(factory.hashCode()); System.out.println(factory.getClass().getName()); System.out.println("二者相等嗎: " + (factory == beanFactory)); }}

驗證結果完全支持官方說明。

DefaultListableBeanFactory

官方對他如此定義:

Spring的{@link ConfigurableListableBeanFactory},{@link BeanDefinitionRegistry}的默認實現 成熟的bean工廠 基于bean定義元數據,可通過后處理器進行擴展

臺前光亮的是BeanFactory,負重前行的卻是DefaultListableBeanFactory,明明是三個人的電影,我卻始終不能有姓名。那么DefaultListableBeanFactory的對象是何時產生的呢?一個新的問題又縈繞在我的心頭。答案其實與IOC容器的初始化密不可分,我在這里不詳敘了。我們只簡單的剖析一下DefaultListableBeanFactory產生對象的心路歷程。 我們在MainContainer中調用了如下構造方法:

public AnnotationConfigApplicationContext(Class>... annotatedClasses) { this(); register(annotatedClasses); refresh();}

因為AnnotationConfigApplicationContext繼承了GenericApplicationContext,所以父類的的構造方法也會同時調用,容器對象就在此時誕生。

public GenericApplicationContext() { this.beanFactory = new DefaultListableBeanFactory();}

然后refresh()調用obtainFreshBeanFactory()。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory(); return getBeanFactory();}

getBeanFactory()是AbstractApplicationContext定義的抽象方法。又由GenericApplicationContext實現。

public final ConfigurableListableBeanFactory getBeanFactory() { return this.beanFactory;}

這里其實就是將自己構造方法產生的對象返回給AnnotationConfigApplicationContext。追蹤到這一層的時候,容器對象的身世之謎才終于被我們揭開。其實ApplicationContext之所以有Beanfactory能力就是因為有關容器的操作他都委托給自己內部的容器對象了。舉個例子:

public T getBean(String name, Class requiredType) throws BeansException { assertBeanFactoryActive(); return getBeanFactory().getBean(name, requiredType);}

這里實際上他并沒有對此方法有詳細的實現,而是通過getBeanFactory()獲取自身內部的容器對象,然后交由ta實現。 現在脈絡應該足夠清晰了。Spring源碼是設計模式的集大成者,這里其實運用的就是組合模式

二者差異

其實官方有他們二者的總結

org.springframework.beans和org.springframework.context包是Spring框架的IoC容器的基礎。BeanFactory 接口提供了一種高級配置機制,能夠管理任何類型的對象。 ApplicationContext 是其子接口。

增加了以下特性:

  • 與Spring的AOP功能輕松集成
  • 消息資源處理(用于國際化)
  • 活動發布
  • 應用層特定的上下文


作者:顏如玉
鏈接:https://juejin.im/post/5e3ea6c16fb9a07cb427c5b4

總結

以上是生活随笔為你收集整理的中getname_Spring IOC中的灵魂伴侣:BeanFactory ApplicationContext的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。