Spring系列中的beanFactory與ApplicationContext
一、BeanFactory
BeanFactory 是 Spring 的“心臟”。它就是 Spring IoC 容器的真面目。Spring 使用 BeanFactory 來實(shí)例化、配置和管理 Bean。
BeanFactory:是IOC容器的核心接口, 它定義了IOC的基本功能,我們看到它主要定義了getBean方法。getBean方法是IOC容器獲取bean對(duì)象和引發(fā)依賴注入的起點(diǎn)。方法的功能是返回特定的名稱的Bean。
BeanFactory 是初始化 Bean 和調(diào)用它們生命周期方法的“吃苦耐勞者”。注意,BeanFactory 只能管理單例(Singleton)Bean 的生命周期。它不能管理原型(prototype,非單例)Bean 的生命周期。這是因?yàn)樵?Bean 實(shí)例被創(chuàng)建之后便被傳給了客戶端,容器失去了對(duì)它們的引用。
BeanFactory有著龐大的繼承、實(shí)現(xiàn)體系,有眾多的子接口、實(shí)現(xiàn)類。
來看一下BeanFactory的基本類體系結(jié)構(gòu)(接口為主):
這是我畫的BeanFactory基本的類體系結(jié)構(gòu),這里沒有包括強(qiáng)大的ApplicationContext體系。
具體:
- 1、BeanFactory作為一個(gè)主接口不繼承任何接口,暫且稱為一級(jí)接口。
- 2、有3個(gè)子接口繼承了它,進(jìn)行功能上的增強(qiáng)。這3個(gè)子接口稱為二級(jí)接口。
- 3、ConfigurableBeanFactory可以被稱為三級(jí)接口,對(duì)二級(jí)接口HierarchicalBeanFactory進(jìn)行了再次增強(qiáng),它還繼承了另一個(gè)外來的接口SingletonBeanRegistry
- 4、ConfigurableListableBeanFactory是一個(gè)更強(qiáng)大的接口,繼承了上述的所有接口,無所不包,稱為四級(jí)接口。
- ?。ㄟ@4級(jí)接口是BeanFactory的基本接口體系。繼續(xù),下面是繼承關(guān)系的2個(gè)抽象類和2個(gè)實(shí)現(xiàn)類:)
- 5、AbstractBeanFactory作為一個(gè)抽象類,實(shí)現(xiàn)了三級(jí)接口ConfigurableBeanFactory大部分功能。
- 6、AbstractAutowireCapableBeanFactory同樣是抽象類,繼承自AbstractBeanFactory,并額外實(shí)現(xiàn)了二級(jí)接口AutowireCapableBeanFactory
- 7、DefaultListableBeanFactory繼承自AbstractAutowireCapableBeanFactory,實(shí)現(xiàn)了最強(qiáng)大的四級(jí)接口ConfigurableListableBeanFactory,并實(shí)現(xiàn)了一個(gè)外來接口BeanDefinitionRegistry,它并非抽象類。
- 8、最后是最強(qiáng)大的XmlBeanFactory,繼承自DefaultListableBeanFactory,重寫了一些功能,使自己更強(qiáng)大。
總結(jié):
BeanFactory的類體系結(jié)構(gòu)看似繁雜混亂,實(shí)際上由上而下井井有條,非常容易理解。
再來看一下BeanFactory的源碼:
<pre>package org.springframework.beans.factory; public interface BeanFactory { /** * 用來引用一個(gè)實(shí)例,或把它和工廠產(chǎn)生的Bean區(qū)分開,就是說,如果一個(gè)FactoryBean的名字為a,那么,&a會(huì)得到那個(gè)Factory */ String FACTORY_BEAN_PREFIX = "&"; /* * 四個(gè)不同形式的getBean方法,獲取實(shí)例 */ Object getBean(String name) throws BeansException; <T> T getBean(String name, Class<T> requiredType) throws BeansException; <T> T getBean(Class<T> requiredType) throws BeansException; Object getBean(String name, Object... args) throws BeansException; boolean containsBean(String name); // 是否存在 boolean isSingleton(String name) throws NoSuchBeanDefinitionException;// 是否為單實(shí)例 boolean isPrototype(String name) throws NoSuchBeanDefinitionException;// 是否為原型(多實(shí)例) boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;// 名稱、類型是否匹配 Class<?> getType(String name) throws NoSuchBeanDefinitionException; // 獲取類型 String[] getAliases(String name);// 根據(jù)實(shí)例的名字獲取實(shí)例的別名 }</pre>
具體:
- 1、4個(gè)獲取實(shí)例的方法。getBean的重載方法。
- 2、4個(gè)判斷的方法。判斷是否存在,是否為單例、原型,名稱類型是否匹配。
- 3、1個(gè)獲取類型的方法、一個(gè)獲取別名的方法。根據(jù)名稱獲取類型、根據(jù)名稱獲取別名。一目了然!
總結(jié):
這10個(gè)方法,很明顯,這是一個(gè)典型的工廠模式的工廠接口。
BeanFactory最常見的實(shí)現(xiàn)類為XmlBeanFactory,可以從classpath或文件系統(tǒng)等獲取資源。
<pre>(1)File file = new File("fileSystemConfig.xml"); Resource resource = new FileSystemResource(file); BeanFactory beanFactory = new XmlBeanFactory(resource);</pre>
<pre>(2) Resource resource = new ClassPathResource("classpath.xml"); BeanFactory beanFactory = new XmlBeanFactory(resource);</pre>
XmlBeanFactory可以加載xml的配置文件。假設(shè)我們有一個(gè)Car類:
<pre>package spring.ioc.demo1; public class Car { private String brand; private String color; private int maxSpeed; public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public int getMaxSpeed() { return maxSpeed; } public void setMaxSpeed(int maxSpeed) { this.maxSpeed = maxSpeed; } public String toString(){ return "the car is:"+ getBrand() + ", color is:" +getColor() +", maxspeed is:"+getMaxSpeed(); } public Car() { } public Car(String brand, String color, int maxSpeed) { this.brand = brand; this.color = color; this.maxSpeed = maxSpeed; } public void introduce() { System.out.println("brand:" + brand + ";color:" + color + ";maxSpeed:" + maxSpeed); } }</pre>
我們通過在applicationContext.xml中配置:
<pre><bean id="car1" class="spring.ioc.demo1.Car" p:brand="spring注入-紅旗001" p:color="spring注入-紫色" p:maxSpeed="520" /></pre>
通過XmlBeanFactory實(shí)現(xiàn)啟動(dòng)Spring IoC容器:
<pre>public static void main(String[] args) { ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); Resource res = resolver.getResource("classpath:applicationContext.xml"); BeanFactory factory = new XmlBeanFactory(res); //ApplicationContext factory=new ClassPathXmlApplicationContext("applicationContext.xml"); Car car = factory.getBean("car1",Car.class); System.out.println("car對(duì)象已經(jīng)初始化完成"); System.out.println(car.getMaxSpeed()); }</pre>
- 1. XmlBeanFactory通過Resource裝載Spring配置信息冰啟動(dòng)IoC容器,然后就可以通過factory.getBean從IoC容器中獲取Bean了。
- 2. 通過BeanFactory啟動(dòng)IoC容器時(shí),并不會(huì)初始化配置文件中定義的Bean,初始化動(dòng)作發(fā)生在第一個(gè)調(diào)用時(shí)。
- 3. 對(duì)于單實(shí)例(singleton)的Bean來說,BeanFactory會(huì)緩存Bean實(shí)例,所以第二次使用getBean時(shí)直接從IoC容器緩存中獲取Bean。
二、ApplicationContext
如果說BeanFactory是Spring的心臟,那么ApplicationContext就是完整的軀體了,ApplicationContext由BeanFactory派生而來,提供了更多面向?qū)嶋H應(yīng)用的功能。在BeanFactory中,很多功能需要以編程的方式實(shí)現(xiàn),而在ApplicationContext中則可以通過配置實(shí)現(xiàn)。
BeanFactorty接口提供了配置框架及基本功能,但是無法支持spring的aop功能和web應(yīng)用。而ApplicationContext接口作為BeanFactory的派生,因而提供BeanFactory所有的功能。而且
ApplicationContext還在功能上做了擴(kuò)展,相較于BeanFactorty,ApplicationContext還提供了以下的功能:
- (1)MessageSource, 提供國際化的消息訪問
- (2)資源訪問,如URL和文件
- (3)事件傳播特性,即支持aop特性
- (4)載入多個(gè)(有繼承關(guān)系)上下文 ,使得每一個(gè)上下文都專注于一個(gè)特定的層次,比如應(yīng)用的web層
ApplicationContext:是IOC容器另一個(gè)重要接口, 它繼承了BeanFactory的基本功能, 同時(shí)也繼承了容器的高級(jí)功能,如:MessageSource(國際化資源接口)、ResourceLoader(資源加載接口)、ApplicationEventPublisher(應(yīng)用事件發(fā)布接口)等。
三、二者區(qū)別
1.BeanFactroy采用的是延遲加載形式來注入Bean的,即只有在使用到某個(gè)Bean時(shí)(調(diào)用getBean()),才對(duì)該Bean進(jìn)行加載實(shí)例化,這樣,我們就不能發(fā)現(xiàn)一些存在的Spring的配置問題。而ApplicationContext則相反,它是在容器啟動(dòng)時(shí),一次性創(chuàng)建了所有的Bean。這樣,在容器啟動(dòng)時(shí),我們就可以發(fā)現(xiàn)Spring中存在的配置錯(cuò)誤。 相對(duì)于基本的BeanFactory,ApplicationContext 唯一的不足是占用內(nèi)存空間。當(dāng)應(yīng)用程序配置Bean較多時(shí),程序啟動(dòng)較慢。
BeanFacotry延遲加載,如果Bean的某一個(gè)屬性沒有注入,BeanFacotry加載后,直至第一次使用調(diào)用getBean方法才會(huì)拋出異常;而ApplicationContext則在初始化自身是檢驗(yàn),這樣有利于檢查所依賴屬性是否注入;所以通常情況下我們選擇使用 ApplicationContext。
應(yīng)用上下文則會(huì)在上下文啟動(dòng)后預(yù)載入所有的單實(shí)例Bean。通過預(yù)載入單實(shí)例bean ,確保當(dāng)你需要的時(shí)候,你就不用等待,因?yàn)樗鼈円呀?jīng)創(chuàng)建好了。
2.BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但兩者之間的區(qū)別是:BeanFactory需要手動(dòng)注冊(cè),而ApplicationContext則是自動(dòng)注冊(cè)。(Applicationcontext比 beanFactory 加入了一些更好使用的功能。而且 beanFactory 的許多功能需要通過編程實(shí)現(xiàn)而 Applicationcontext 可以通過配置實(shí)現(xiàn)。比如后處理 bean , Applicationcontext 直接配置在配置文件即可而 beanFactory 這要在代碼中顯示的寫出來才可以被容器識(shí)別。 )
3.beanFactory主要是面對(duì)與 spring 框架的基礎(chǔ)設(shè)施,面對(duì) spring 自己。而 Applicationcontex 主要面對(duì)與 spring 使用的開發(fā)者。基本都會(huì)使用 Applicationcontex 并非 beanFactory 。
四、總結(jié)
作用:
- 1. BeanFactory負(fù)責(zé)讀取bean配置文檔,管理bean的加載,實(shí)例化,維護(hù)bean之間的依賴關(guān)系,負(fù)責(zé)bean的聲明周期。
- 2. ApplicationContext除了提供上述BeanFactory所能提供的功能之外,還提供了更完整的框架功能:
- a. 國際化支持
- b. 資源訪問:Resource rs = ctx. getResource(“classpath:config.properties”), “file:c:/config.properties”
- c. 事件傳遞:通過實(shí)現(xiàn)ApplicationContextAware接口
- 3. 常用的獲取ApplicationContext
FileSystemXmlApplicationContext:從文件系統(tǒng)或者url指定的xml配置文件創(chuàng)建,參數(shù)為配置文件名或文件名數(shù)組,有相對(duì)路徑與絕對(duì)路徑。
<pre>ApplicationContext factory=new FileSystemXmlApplicationContext("src/applicationContext.xml"); ApplicationContext factory=new FileSystemXmlApplicationContext("E:/Workspaces/MyEclipse 8.5/Hello/src/applicationContext.xml");</pre>
ClassPathXmlApplicationContext:從classpath的xml配置文件創(chuàng)建,可以從jar包中讀取配置文件。
ClassPathXmlApplicationContext 編譯路徑總有三種方式:
<pre>ApplicationContext factory = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); ApplicationContext factory = new ClassPathXmlApplicationContext("applicationContext.xml"); ApplicationContext factory = new ClassPathXmlApplicationContext("file:E:/Workspaces/MyEclipse 8.5/Hello/src/applicationContext.xml");</pre>
XmlWebApplicationContext:從web應(yīng)用的根目錄讀取配置文件,需要先在web.xml中配置,可以配置監(jiān)聽器或者servlet來實(shí)現(xiàn)
<pre><listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener></pre>
或
<pre><servlet> <servlet-name>context</servlet-name> <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet></pre>
這兩種方式都默認(rèn)配置文件為web-inf/applicationContext.xml,也可使用context-param指定配置文件
<pre><context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/myApplicationContext.xml</param-value> </context-param></pre>
到此這篇關(guān)于Spring系列中的beanFactory與ApplicationContext的文章就介紹到這了,更多相關(guān)Spring beanFactory與ApplicationContext內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JAVA內(nèi)存模型和Happens-Before規(guī)則知識(shí)點(diǎn)講解
在本篇文章里小編給大家整理的是一篇關(guān)于JAVA內(nèi)存模型和Happens-Before規(guī)則知識(shí)點(diǎn)內(nèi)容,有需要的朋友們跟著學(xué)習(xí)下。2020-11-11springboot項(xiàng)目啟動(dòng)指定對(duì)應(yīng)環(huán)境的方法
這篇文章主要介紹了springboot項(xiàng)目啟動(dòng)指定對(duì)應(yīng)環(huán)境的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-08-08SpringBoot中利用AOP和攔截器實(shí)現(xiàn)自定義注解
本文將通過攔截器+AOP實(shí)現(xiàn)自定義注解,在這里攔截器充當(dāng)在指定注解處要執(zhí)行的方法,aop負(fù)責(zé)將攔截器的方法和要注解生效的地方做一個(gè)織入,感興趣的可以嘗試一下2022-06-06關(guān)于struts返回對(duì)象json格式數(shù)據(jù)的方法
以下為大家介紹,關(guān)于struts返回對(duì)象json格式數(shù)據(jù)的方法,希望對(duì)有需要的朋友有所幫助。2013-04-04spring-boot.version2.6升級(jí)到2.7.18后security報(bào)錯(cuò)問題
這篇文章主要介紹了spring-boot.version2.6升級(jí)到2.7.18后security報(bào)錯(cuò)問題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08