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>