1、BeanFactory
BeanFactory 是 Spring 的「心臟」。它就是 Spring IoC 容器的真面目。Spring 使用 BeanFactory 來實例化、配置和管理 Bean。web
BeanFactory:是IOC容器的核心接口, 它定義了IOC的基本功能,咱們看到它主要定義了getBean方法。getBean方法是IOC容器獲取bean對象和引起依賴注入的起點。方法的功能是返回特定的名稱的Bean。spring
BeanFactory 是初始化 Bean 和調用它們生命週期方法的「吃苦耐勞者」。注意,BeanFactory 只能管理單例(Singleton)Bean 的生命週期。它不能管理原型(prototype,非單例)Bean 的生命週期。這是由於原型 Bean 實例被建立以後便被傳給了客戶端,容器失去了對它們的引用。編程
BeanFactory有着龐大的繼承、實現體系,有衆多的子接口、實現類。來看一下BeanFactory的基本類體系結構(接口爲主):數組
這是我畫的BeanFactory基本的類體系結構,這裏沒有包括強大的ApplicationContext體系。
具體:
一、BeanFactory做爲一個主接口不繼承任何接口,暫且稱爲一級接口。
二、有3個子接口繼承了它,進行功能上的加強。這3個子接口稱爲二級接口。
三、ConfigurableBeanFactory能夠被稱爲三級接口,對二級接口HierarchicalBeanFactory進行了再次加強,它還繼承了另外一個外來的接口SingletonBeanRegistry
四、ConfigurableListableBeanFactory是一個更強大的接口,繼承了上述的全部接口,無所不包,稱爲四級接口。
(這4級接口是BeanFactory的基本接口體系。繼續,下面是繼承關係的2個抽象類和2個實現類:)
五、AbstractBeanFactory做爲一個抽象類,實現了三級接口ConfigurableBeanFactory大部分功能。
六、AbstractAutowireCapableBeanFactory一樣是抽象類,繼承自AbstractBeanFactory,並額外實現了二級接口AutowireCapableBeanFactory
七、DefaultListableBeanFactory繼承自AbstractAutowireCapableBeanFactory,實現了最強大的四級接口ConfigurableListableBeanFactory,並實現了一個外來接口BeanDefinitionRegistry,它並不是抽象類。
八、最後是最強大的XmlBeanFactory,繼承自DefaultListableBeanFactory,重寫了一些功能,使本身更強大。緩存
總結:
BeanFactory的類體系結構看似繁雜混亂,實際上由上而下層次分明,很是容易理解。app
再來看一下BeanFactory的源碼:框架
package org.springframework.beans.factory; public interface BeanFactory { /** * 用來引用一個實例,或把它和工廠產生的Bean區分開,就是說,若是一個FactoryBean的名字爲a,那麼,&a會獲得那個Factory */ String FACTORY_BEAN_PREFIX = "&"; /* * 四個不一樣形式的getBean方法,獲取實例 */ 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;// 是否爲單實例 boolean isPrototype(String name) throws NoSuchBeanDefinitionException;// 是否爲原型(多實例) boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;// 名稱、類型是否匹配 Class<?> getType(String name) throws NoSuchBeanDefinitionException; // 獲取類型 String[] getAliases(String name);// 根據實例的名字獲取實例的別名 }
具體:
一、4個獲取實例的方法。getBean的重載方法。
二、4個判斷的方法。判斷是否存在,是否爲單例、原型,名稱類型是否匹配。
三、1個獲取類型的方法、一個獲取別名的方法。根據名稱獲取類型、根據名稱獲取別名。一目瞭然!
總結:
這10個方法,很明顯,這是一個典型的工廠模式的工廠接口。ui
BeanFactory最多見的實現類爲XmlBeanFactory,能夠從classpath或文件系統等獲取資源。this
(1)File file = new File("fileSystemConfig.xml"); Resource resource = new FileSystemResource(file); BeanFactory beanFactory = new XmlBeanFactory(resource);
(2) Resource resource = new ClassPathResource("classpath.xml"); BeanFactory beanFactory = new XmlBeanFactory(resource);
XmlBeanFactory能夠加載xml的配置文件。假設咱們有一個Car類:url
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); } }
咱們經過在applicationContext.xml中配置:
<bean id="car1" class="spring.ioc.demo1.Car" p:brand="spring注入-紅旗001" p:color="spring注入-紫色" p:maxSpeed="520" />
經過XmlBeanFactory實現啓動Spring IoC容器:
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對象已經初始化完成"); System.out.println(car.getMaxSpeed()); }
1. XmlBeanFactory經過Resource裝載Spring配置信息冰啓動IoC容器,而後就能夠經過factory.getBean從IoC容器中獲取Bean了。
2. 經過BeanFactory啓動IoC容器時,並不會初始化配置文件中定義的Bean,初始化動做發生在第一個調用時。
3. 對於單實例(singleton)的Bean來講,BeanFactory會緩存Bean實例,因此第二次使用getBean時直接從IoC容器緩存中獲取Bean。
2、ApplicationContext
若是說BeanFactory是Spring的心臟,那麼ApplicationContext就是完整的軀體了,ApplicationContext由BeanFactory派生而來,提供了更多面向實際應用的功能。在BeanFactory中,不少功能須要以編程的方式實現,而在ApplicationContext中則能夠經過配置實現。
BeanFactorty接口提供了配置框架及基本功能,可是沒法支持spring的aop功能和web應用。而ApplicationContext接口做爲BeanFactory的派生,於是提供BeanFactory全部的功能。並且ApplicationContext還在功能上作了擴展,相較於BeanFactorty,ApplicationContext還提供瞭如下的功能:
(1)MessageSource, 提供國際化的消息訪問
(2)資源訪問,如URL和文件
(3)事件傳播特性,即支持aop特性
(4)載入多個(有繼承關係)上下文 ,使得每個上下文都專一於一個特定的層次,好比應用的web層
ApplicationContext:是IOC容器另外一個重要接口, 它繼承了BeanFactory的基本功能, 同時也繼承了容器的高級功能,如:MessageSource(國際化資源接口)、ResourceLoader(資源加載接口)、ApplicationEventPublisher(應用事件發佈接口)等。
3、兩者區別
1.BeanFactroy採用的是延遲加載形式來注入Bean的,即只有在使用到某個Bean時(調用getBean()),纔對該Bean進行加載實例化,這樣,咱們就不能發現一些存在的Spring的配置問題。而ApplicationContext則相反,它是在容器啓動時,一次性建立了全部的Bean。這樣,在容器啓動時,咱們就能夠發現Spring中存在的配置錯誤。 相對於基本的BeanFactory,ApplicationContext 惟一的不足是佔用內存空間。當應用程序配置Bean較多時,程序啓動較慢。
BeanFacotry延遲加載,若是Bean的某一個屬性沒有注入,BeanFacotry加載後,直至第一次使用調用getBean方法纔會拋出異常;而ApplicationContext則在初始化自身是檢驗,這樣有利於檢查所依賴屬性是否注入;因此一般狀況下咱們選擇使用 ApplicationContext。
應用上下文則會在上下文啓動後預載入全部的單實例Bean。經過預載入單實例bean ,確保當你須要的時候,你就不用等待,由於它們已經建立好了。
2.BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但二者之間的區別是:BeanFactory須要手動註冊,而ApplicationContext則是自動註冊。(Applicationcontext比 beanFactory 加入了一些更好使用的功能。並且 beanFactory 的許多功能須要經過編程實現而 Applicationcontext 能夠經過配置實現。好比後處理 bean , Applicationcontext 直接配置在配置文件便可而 beanFactory 這要在代碼中顯示的寫出來才能夠被容器識別。 )
3.beanFactory主要是面對與 spring 框架的基礎設施,面對 spring 本身。而 Applicationcontex 主要面對與 spring 使用的開發者。基本都會使用 Applicationcontex 並不是 beanFactory 。
4、總結
做用:
1. BeanFactory負責讀取bean配置文檔,管理bean的加載,實例化,維護bean之間的依賴關係,負責bean的聲明週期。
2. ApplicationContext除了提供上述BeanFactory所能提供的功能以外,還提供了更完整的框架功能:
a. 國際化支持
b. 資源訪問:Resource rs = ctx. getResource(「classpath:config.properties」), 「file:c:/config.properties」
c. 事件傳遞:經過實現ApplicationContextAware接口
3. 經常使用的獲取ApplicationContext
FileSystemXmlApplicationContext:從文件系統或者url指定的xml配置文件建立,參數爲配置文件名或文件名數組,有相對路徑與絕對路徑。
ApplicationContext factory=new FileSystemXmlApplicationContext("src/applicationContext.xml"); ApplicationContext factory=new FileSystemXmlApplicationContext("E:/Workspaces/MyEclipse 8.5/Hello/src/applicationContext.xml");
ClassPathXmlApplicationContext:從classpath的xml配置文件建立,能夠從jar包中讀取配置文件。ClassPathXmlApplicationContext 編譯路徑總有三種方式:
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");
XmlWebApplicationContext:從web應用的根目錄讀取配置文件,須要先在web.xml中配置,能夠配置監聽器或者servlet來實現
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
或
<servlet> <servlet-name>context</servlet-name> <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet>
這兩種方式都默認配置文件爲web-inf/applicationContext.xml,也可以使用context-param指定配置文件
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/myApplicationContext.xml</param-value> </context-param>