Spring系列之beanFactory与ApplicationContext
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Spring系列之beanFactory与ApplicationContext
⼀、BeanFactory
BeanFactory 是 Spring 的“⼼脏”。
它就是 Spring IoC 容器的真⾯⽬。
Spring 使⽤ BeanFactory 来实例化、配置和管理 Bean。
BeanFactory:是IOC容器的核⼼接⼝,它定义了IOC的基本功能,我们看到它主要定义了getBean⽅法。
getBean⽅法是IOC容器获取bean 对象和引发依赖注⼊的起点。
⽅法的功能是返回特定的名称的Bean。
BeanFactory 是初始化 Bean 和调⽤它们⽣命周期⽅法的“吃苦耐劳者”。
注意,BeanFactory 只能管理单例(Singleton)Bean 的⽣命周期。
它不能管理原型(prototype,⾮单例)Bean 的⽣命周期。
这是因为原型 Bean 实例被创建之后便被传给了客户端,容器失去了对它们的引⽤。
BeanFactory有着庞⼤的继承、实现体系,有众多的⼦接⼝、实现类。
来看⼀下BeanFactory的基本类体系结构(接⼝为主):
这是我画的BeanFactory基本的类体系结构,这⾥没有包括强⼤的ApplicationContext体系。
具体:
1、BeanFactory作为⼀个主接⼝不继承任何接⼝,暂且称为⼀级接⼝。
2、有3个⼦接⼝继承了它,进⾏功能上的增强。
这3个⼦接⼝称为⼆级接⼝。
3、ConfigurableBeanFactory可以被称为三级接⼝,对⼆级接⼝HierarchicalBeanFactory进⾏了再次增强,它还继承了另⼀个外来的接⼝SingletonBeanRegistry
4、ConfigurableListableBeanFactory是⼀个更强⼤的接⼝,继承了上述的所有接⼝,⽆所不包,称为四级接⼝。
(这4级接⼝是BeanFactory的基本接⼝体系。
继续,下⾯是继承关系的2个抽象类和2个实现类:)
5、AbstractBeanFactory作为⼀个抽象类,实现了三级接⼝ConfigurableBeanFactory⼤部分功能。
6、AbstractAutowireCapableBeanFactory同样是抽象类,继承⾃AbstractBeanFactory,并额外实现了⼆级接⼝AutowireCapableBeanFactory
7、DefaultListableBeanFactory继承⾃AbstractAutowireCapableBeanFactory,实现了最强⼤的四级接⼝ConfigurableListableBeanFactory,并实现了⼀个外来接⼝BeanDefinitionRegistry,它并⾮抽象类。
8、最后是最强⼤的XmlBeanFactory,继承⾃DefaultListableBeanFactory,重写了⼀些功能,使⾃⼰更强⼤。
总结:
BeanFactory的类体系结构看似繁杂混乱,实际上由上⽽下井井有条,⾮常容易理解。
再来看⼀下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);// 根据实例的名字获取实例的别名
}
具体:
1、4个获取实例的⽅法。
getBean的重载⽅法。
2、4个判断的⽅法。
判断是否存在,是否为单例、原型,名称类型是否匹配。
3、1个获取类型的⽅法、⼀个获取别名的⽅法。
根据名称获取类型、根据名称获取别名。
⼀⽬了然!
总结:
这10个⽅法,很明显,这是⼀个典型的⼯⼚模式的⼯⼚接⼝。
BeanFactory最常见的实现类为XmlBeanFactory,可以从classpath或⽂件系统等获取资源。
(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类:
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。
⼆、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(应⽤事件发布接⼝)等。
三、⼆者区别
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 。
四、总结
作⽤:
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>。