前面学习了spring的BeanFactory的加载过程,完成了基本的bean的注册和取出。但是在我们平常使用的过程中,经常使用的是ApplicationContext,那么ApplicationContext跟BeanFactory有什么关系呢?ApplicationContext又为我们做了些什么呢?
1.两种容器
spring提供了两种容器,一是BeanFactory,一个是ApplicationContext应用上下文。
BeanFactory是spring比较原始 的Factory,例如xmlBeanFactory是一种典型的BeanFactory。原始的BeanFactory无法支持spring的许多插件,比如AOP功能,Web应用等。
ApplicationContext接口,继承于BeanFactory,能够提供BeanFactory的所有功能,它是一种更加面向框架的工作方式,此外ApplicationContext还提供 了如下功能:
MessageSource,提供国际化支持;资源访问,例如url和文件;事件传播;载入多个(有继承关系的上下文),使每个上下文都有一个特定的层次。比如Web。
2.对比?
(1)相同点
都是通过xlm来加载factory容器。
(2)不同点
A Bean何时加载?
BeanFactory是采用延时加载来注入Bean的,即只有在使用某个Bean时,调用getBean方法,来对该Bean进行加载实例化。
ApplicationContext则相反, 它是在容器启动时,一次创建所有的Bean,这样,在容器启动时,我们就可以发现Spring配置中存在的问题。
B Applicationc 相比Beanfactory提供了更多的功能
国际化支持
资源访问:Resource rs = ctx. getResource(“classpath:config.properties”), “file:c:/config.properties”
事件传递:通过实现ApplicationContextAware接口
3.Application主要类使用
(1)ApplicationContext的三个实现类:
a、ClassPathXmlApplication:把上下文文件当成类路径资源
b、FileSystemXmlApplication:从文件系统中的XML文件载入上下文定义信息
c、XmlWebApplicationContext:从Web系统中的XML文件载入上下文定义信息
在springioc的例子中,我们产生factory的方式如下:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
这样产生applicationContext就会有一些弊端,每次加载Bean的时候,都会产生这个工厂。解决方法如下:在web启动的时候 ,将ApplicationContext转到ServletContext中,因为web应用的Servlet都将共享一个ServletContext对象,那么就可以利用ServletcontextListener去监听ServletContext事件,当web启动的时候,就将applicationContext转载到ServletContext中。
Spring容器底层已经为我们想到了这一点, 在spring-web-xxx-release.jar包中有一个 已经实现ServletContextListener的类
public class ContextLoaderListener
extends Object
implements ServletContextListener
作用如下:
作用:在启动Web容器时,自动装配Spring applicationContext.xml的配置信息。
4.tinyspring 手动实现了applicationContext
(1)ApplicationContext接口
/**
* Created by 栗振娟 on 2017/10/2.
* ApplicationContext是一个接口,继承BeanFactory接口
*/
public interface ApplicationContext extends BeanFactory{
}
(2)AbstractApplicationContext
/**
* Created by 栗振娟 on 2017/10/2.
*/
public abstract class AbstractApplicationContext implements ApplicationContext{
protected AbstractBeanFactory abstractBeanFactory;
//构造方法
public AbstractApplicationContext(AbstractBeanFactory beanFactory){
this.abstractBeanFactory=beanFactory;
}
//交给子类实现
public void refresh() throws Exception{
}
//根据名称来获得bean
@Override
public Object getBean(String beanName) throws Exception {
return abstractBeanFactory.getBean(beanName);
}
(3)ClassPathXmlApplicationContext
/**
* Created by 栗振娟 on 2017/10/2.
*/
public class ClassPathXmlApplicationContext extends AbstractApplicationContext{
private String configLocation;
public ClassPathXmlApplicationContext(String configLocation) throws Exception {
this(configLocation,new AutowireCapableBeanFactory());
}
public ClassPathXmlApplicationContext(String configLocation,AbstractBeanFactory beanFactory) throws Exception {
super(beanFactory);
this.configLocation=configLocation;
refresh();
}
//主要的加载BeanFacatory的方法
@Override
public void refresh()throws Exception{
XmlBeanDefinitionReader xmlBeanDefinitionReader=new XmlBeanDefinitionReader(new ResourceLoader());
xmlBeanDefinitionReader.loadBeanDefinition(configLocation);
for(Map.Entry<String,BeanDefinition> beanDefinitionEntry:xmlBeanDefinitionReader.getRegistry().entrySet()){
abstractBeanFactory.registerBeanDefinition(beanDefinitionEntry.getKey(),beanDefinitionEntry.getValue());
}
}
}
5.推荐
spring之ContextLoaderListener的作用