BeanFactory是spring中比较原始的Factory。如XMLBeanFactory就是一种典型的BeanFactory。原始的BeanFactory无法支持spring的许多插件,如AOP功能、Web应用等。
ApplicationContext接口,它由BeanFactory接口派生而来,ApplicationContext包含BeanFactory的所有功能,通常建议比BeanFactory优先。
用处:
平常在使用的 Spring 的过程中,我想大家应该用到的都是 ApplicationContext 用来读取配置文件,然后启动 Spring 容器。但是,我们使用过程中,肯定也知道存在 Beanfactory 的存在。那么我们为什么都是使用 ApplicationContext,而非 BeanFactory 的呢?
两种方式获取Bean:
现在写个用 BeanFactory 来获取定义的 bean 程序。
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
beanDefinitionReader.loadBeanDefinitions(new ClassPathResource("applicationContext.xml"));
DemoServiceImpl demo = (DemoServiceImpl) beanFactory.getBean("demo");
现在我们对比用 ApplicationContext 写一个获取 bean 的程序:
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
DemoService demo = (DemoService) ctx.getBean("demo");
从上面两个程序对比可以看出,使用 Beanfactory 来获取 Bean ,我们还额外实现相关类。这些类我们使用 ApplicationContext 根本无需实现。那么为什么是这样的那?接下去我们查看 Spring 相关的源码。
Spring源码
上面两个程序我们看出 ApplicationContext 与 BeanFactory 都存在 getBean 这个核心方法。这个时候自然想到。这两个类是否实现了相同的接口。使用 Idea 类图功能,得到了下面了关系图。
从这个图中我们清晰看出 ApplicationContext 继承 BeanFactory,自然的 ApplicationContext 就拥有了 BeanFactory 的相关方法了。然后再看其实现类相关代码,画出下面一张类图。
从这张类图可以看出,AbstractRefreshableApplicationContext 存在的 Beanfactory 属性,我们再查看 ApplicationContext getBean 方法实际上最后委托 BeanFactory 的 getBean 方法。
1、利用MessageSource进行国际化
BeanFactory是不支持国际化功能的,因为BeanFactory没有扩展Spring中MessageResource接口。相反,由于ApplicationContext扩展了MessageResource接口,因而具有消息处理的能力(i18N)。
2、强大的事件机制(Event)
基本上牵涉到事件(Event)方面的设计,就离不开观察者模式。不明白观察者模式的朋友,最好上网了解下。因为,这种模式在java开发中是比较常用的,又是比较重要的。
ApplicationContext的事件机制主要通过ApplicationEvent和ApplicationListener这两个接口来提供的,和java swing中的事件机制一样。即当ApplicationContext中发布一个事件的时,所有扩展了ApplicationListener的Bean都将会接受到这个事件,并进行相应的处理。
Spring提供了部分内置事件,主要有以下几种:
ContextRefreshedEvent :ApplicationContext发送该事件时,表示该容器中所有的Bean都已经被装载完成,此ApplicationContext已就绪可用
ContextStartedEvent:生命周期 beans的启动信号
ContextStoppedEvent: 生命周期 beans的停止信号
ContextClosedEvent:ApplicationContext关闭事件,则context不能刷新和重启,从而所有的singleton bean全部销毁(因为singleton bean是存在容器缓存中的)
虽然,spring提供了许多内置事件,但用户也可根据自己需要来扩展spriong中的事物。注意,要扩展的事件都要实现ApplicationEvent接口。
3.底层资源的访问
ApplicationContext扩展了ResourceLoader(资源加载器)接口,从而可以用来加载多个Resource,而BeanFactory是没有扩展ResourceLoader
4.其它区别
1).BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,这样,我们就不能发现一些存在的Spring的配置问题。而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean,也可以选择开启懒加载。这样,在容器启动时,我们就可以发现Spring中存在的配置错误。
2).BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册