BeanFactory与ApplicationContext
我对Spring Framework相当陌生,为了评估Spring MVC在即将到来的公司项目中的使用,我一直在玩弄它,并将几个示例应用程序放在一起。 到目前为止,我真的很喜欢我在Spring MVC中看到的东西,看起来很容易使用,并鼓励您编写对unit testing非常友好的类。
就像一个练习,我正在为我的一个样本/testing项目写一个主要的方法。 我不清楚的一件事情是BeanFactory
和ApplicationContext
之间的确切区别 – 适用于哪些条件?
我明白, ApplicationContext
扩展了BeanFactory
,但如果我只是写一个简单的主要方法,我是否需要ApplicationContext
提供的额外function? ApplicationContext
提供了什么样的额外function?
除了回答“我应该在main()方法中使用哪一个”之外,在这种情况下,我应该使用哪种实现方式,是否有任何标准或准则? 我的main()方法是否应该依赖于bean /应用程序configuration写成XML格式 – 这是一个安全的假设,还是我将用户locking到特定的东西?
这个答案在Web环境中是否发生了变化 – 如果我的任何类需要了解Spring,他们是否更需要ApplicationContext
?
谢谢你的帮助。 我知道很多这些问题都可能在参考手册中得到解答,但是我很难find这两个接口的明确分解以及每个接口的优缺点,而不需要通过手册上的细齿梳来阅读。
春季的文档很棒: 3.8.1。 BeanFactory或ApplicationContext? 。 他们有一个比较表,我会张贴一个片段:
豆厂
- Bean实例化/布线
应用上下文
- Bean实例化/布线
- 自动BeanPostProcessor注册
- 自动BeanFactoryPostProcessor注册
- 便捷的MessageSource访问(针对i18n)
- ApplicationEvent发布
所以,如果你需要Application Context方面的任何一点,你应该使用ApplicationContext。
对我来说,在ApplicationContext
上selectBeanFactory
的主要区别似乎是ApplicationContext
会预先实例化所有的bean。 从春季文档:
当bean实际创build时,Spring会尽可能晚地设置属性并解决依赖关系。 这意味着,如果创build该对象或其某个依赖关系时遇到问题,则在请求对象时,正确加载的Spring容器可能会稍后生成exception。 例如,由于缺less或无效的属性,bean抛出exception。 某些configuration问题的可能延迟的可见性是为什么ApplicationContext实现默认预先实例化单例bean。 在实际需要这些Bean之前,需要花费一定的时间和内存来创build这些bean,但是在创buildApplicationContext时发现configuration问题,而不是在以后。 你仍然可以重写这个默认行为,这样singleton bean将会延迟初始化,而不是预先实例化。
鉴于此,我最初selectBeanFactory
用于集成/性能testing,因为我不想加载整个应用程序来testing孤立的bean。 但是 – 有人纠正我,如果我错了 – BeanFactory
不支持classpath
XMLconfiguration。 所以BeanFactory
和ApplicationContext
都提供了我想要的重要function,但都没有。
据我所知,关于重写默认实例化行为的文档中的注释发生在configuration中,并且是每个bean,所以我不能只在XML文件中设置“lazy-init”属性,或者我坚持维护一个版本的testing和一个部署。
我最终做的是扩展ClassPathXmlApplicationContext
来延迟加载bean,以便在testing中使用,如下所示:
public class LazyLoadingXmlApplicationContext extends ClassPathXmlApplicationContext { public LazyLoadingXmlApplicationContext(String[] configLocations) { super(configLocations); } /** * Upon loading bean definitions, force beans to be lazy-initialized. * @see org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.xml.XmlBeanDefinitionReader) */ @Override protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException { super.loadBeanDefinitions(reader); for (String name: reader.getBeanFactory().getBeanDefinitionNames()) { AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) reader.getBeanFactory().getBeanDefinition(name); beanDefinition.setLazyInit(true); } } }
为了补充Miguel Ping所做的回答,下面是文档中另一部分的答案:
短版本:使用ApplicationContext,除非你有一个非常好的理由不这样做。 对于那些正在寻求上述build议的'但为什么'更深入的人,请继续阅读。
(发布这个任何未来的spring新手谁可能会读这个问题)
-
ApplicationContext
比BeanFactory
更BeanFactory
-
在新的Spring版本中,
BeanFactory
被ApplicationContext
replace。 但是BeanFactory
仍然存在向后兼容性 -
ApplicationContext extends BeanFactory
并具有以下优点- 它支持短信的国际化
- 它支持事件发布给注册的监听者
- 访问诸如URL和文件之类的资源
Spring提供了两种IOC容器,一种是
XMLBeanFactory
,另一种是ApplicationContext
。
+---------------------------------------+-----------------+--------------------------------+ | | XMLBeanFactory | ApplicationContext | +---------------------------------------+-----------------+--------------------------------+ | Annotation support | No | Yes | | BeanPostProcessor Registration | Manual | Automatic | | implimentation | XMLBeanFactory | ClassPath/FileSystem/WebXmlApplicationContext| | internationalization | No | Yes | | Enterprise services | No | Yes | | ApplicationEvent publication | No | Yes | +---------------------------------------+-----------------+--------------------------------+
- FileSystemXmlApplicationContext:通过完整path加载的Bean。
- ClassPathXmlApplicationContext:通过CLASSPATH加载的Bean
- WebXmlApplicationContext:通过Web应用程序上下文加载的Bean。
我认为最好总是使用ApplicationContext,除非你像其他人一样在移动环境中。 ApplicationContext具有更多的function,你一定要使用PostOpenProcessors,如RequiredAnnotationBeanPostProcessor,AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor,这将帮助你简化你的Springconfiguration文件,你可以在bean中使用@Required,@PostConstruct,@Resource等注释。
即使你没有使用ApplicationContext提供的所有东西,最好还是使用它,然后如果你决定使用一些资源的东西,如消息或后处理器,或者其他模式来添加事务性的build议等,将已经有一个ApplicationContext,将不需要更改任何代码。
如果你正在编写一个独立的应用程序,使用ClassPathXmlApplicationContext将ApplicationContext加载到你的main方法中,然后获取主bean并调用run()(或者其他方法)来启动你的应用程序。 如果您正在编写Web应用程序,请使用web.xml中的ContextLoaderListener,以便创buildApplicationContext,并且您可以稍后从ServletContext获取它,而不pipe您是使用JSP,JSF,JSTL,struts,Tapestry等。
另外,请记住,您可以使用多个Springconfiguration文件,您可以通过列出构造函数中的所有文件(或将其列在ContextLoaderListener的上下文参数中)来创buildApplicationContext,也可以只加载一个主configuration文件import报表。 您可以通过使用<import resource =“otherfile.xml”/>将Springconfiguration文件导入到另一个Springconfiguration文件中,这在编程创build主方法中的ApplicationContext并仅载入一个Springconfiguration文件时非常有用。
- BeanFactory:不支持基于Annotation的dependency injection。
- ApplicationContext:支持基于注解的dependency injection。 – @ Autowired,@PreDestroy
- BeanFactory:不支持
- ApplicationContext:应用程序上下文可以将事件发布到注册为侦听器的Bean
- BeanFactory:不支持访问Message Bundle的方式(国际化(I18N)
- ApplicationContext:支持国际化(I18N)消息。
- BeanFactory:不支持。
- ApplicationContext:支持许多企业服务,如JNDI访问,EJB集成,远程处理。
- BeanFactory:默认情况下它支持延迟加载
- ApplicationContext:它默认支持Aggresive加载。
ApplicationContext:加载springconfiguration文件中configuration的spring bean,并在spring bean的生命周期和WHEN CONTAINER STARTS之间进行pipe理。它不会等到getBean(“springbeanref”)被调用。
BeanFactory它加载Springconfiguration文件中configuration的Spring Bean,当我们调用getBean(“springbeanref”)的时候pipe理spring bean的生命周期。所以当Spring bean生命周期开始时调用getBean(“springbeanref”) 。
在大多数情况下,ApplicationContext是首选的,除非您需要保存资源,比如在移动应用程序上。
我不确定取决于XML格式,但我相当确定ApplicationContext的最常见的实现是XML的,如ClassPathXmlApplicationContext,XmlWebApplicationContext和FileSystemXmlApplicationContext。 这是我曾经使用过的唯一三个。
如果你开发一个Web应用程序,可以肯定地说你需要使用XmlWebApplicationContext。
如果你想让你的bean知道Spring,你可以让它们实现BeanFactoryAware和/或ApplicationContextAware,所以你可以使用BeanFactory或ApplicationContext并select实现哪个接口。
BeanFactory和ApplicationContext都是从你的spring IOC容器获取bean的方法,但是仍然有一些不同。
BeanFactory是实例化,configuration和pipe理一些bean的实际容器。 这些bean通常是相互协作的,因此彼此之间有依赖关系。 这些依赖关系反映在BeanFactory使用的configuration数据中。
BeanFactory和ApplicationContext都是Java接口,ApplicationContext扩展了BeanFactory。 它们都是使用XMLconfiguration文件的configuration。 简而言之,BeanFactory提供了基本的控制反转( IoC )和dependency injection( DI )function,而ApplicationContext提供了高级function。
一个BeanFactory由接口“ org.springframework.beans.factory ”表示,其中BeanFactory有多个实现。
ClassPathResource resource = new ClassPathResource("appConfig.xml"); XmlBeanFactory factory = new XmlBeanFactory(resource);
区别
-
调用getBean()方法时, BeanFactory实例化bean,而Container启动时ApplicationContext实例化Singleton bean,它不会等待getBean()被调用。
-
BeanFactory不支持国际化,但ApplicationContext提供对它的支持。
-
BeanFactory与ApplicationContext之间的另一个区别是能够将事件发布到注册为侦听器的bean。
-
BeanFactory接口的stream行实现之一是XMLBeanFactory,而ApplicationContext接口的stream行实现之一是ClassPathXmlApplicationContext 。
-
如果您正在使用自动连线并使用BeanFactory ,那么您需要使用API注册AutoWiredBeanPostProcessor ,如果您使用的是ApplicationContext,则可以使用API进行configuration。 总结BeanFactory可以用于testing和非生产用途,但ApplicationContext是更多特性丰富的容器实现,应该比BeanFactory更受青睐
-
BeanFactory默认支持Lazy加载,而ApplicationContext默认支持Aggresive加载。
Bean Factory的特性matrix与来自Spring文档的应用上下文的特性matrix
BeanFacotry和ApplicationContextfunction的屏幕截图
一个。 bean工厂和应用程序上下文之间的一个区别是前者只在调用getBean()方法时实例化bean,而ApplicationContext在容器启动时实例化Singleton bean,而不等待getBean被调用。
湾
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
要么
ApplicationContext context = new ClassPathXmlApplicationContext{"spring_dao.xml","spring_service.xml};
您可以根据您的项目要求使用一个或多个xml文件。 因为我在这里使用了两个xml文件,即一个用于dao类的其他服务类的configuration细节。 这里ClassPathXmlApplicationContext是ApplicationContext的子元素。
C。 BeanFactory容器是基本容器,它只能创build对象并注入依赖关系。 但是我们不能附加安全性,事务,消息等其他服务来提供我们必须使用ApplicationContext Container的所有服务。
d。 BeanFactory不提供国际化的支持,例如i18n,但是ApplicationContext为它提供了支持。
即 BeanFactory容器不支持AutoScanning(基于支持注解的dependency injection)的function,但支持ApplicationContext容器。
F。 Beanfactory容器将不会创build一个bean对象,直到请求时间。 这意味着Beanfactory容器懒洋洋地加载bean。 而ApplicationContext容器只在加载的时候创buildSingleton bean的对象。 这意味着有早期的加载。
G。 Beanfactory容器只支持两个范围(单例和原型)的bean。 但是ApplicationContext容器支持所有的bean作用域。
BeanFactory和ApplicationContext之间的区别如下:
- BeanFactory使用延迟初始化, 但 ApplicationContext使用预先初始化。 在BeanFactory的情况下,在调用getBeans()方法时创buildbean,但在创buildApplicationContext对象时,在ApplicationContext的情况下创buildbean。
- BeanFactory使用语法显式地提供资源对象, 但是 ApplicationContext自己创build和pipe理资源对象。
- BeanFactory不支持国际化, 但 ApplicationContext支持国际化。
- 不支持基于BeanFactory注解的dependency injection, 但 ApplicationContext支持基于注解的dependency injection。
使用BeanFactory:
BeanFactory beanfactory = new XMLBeanFactory(new FileSystemResource("spring.xml")); Triangle triangle =(Triangle)beanFactory.getBean("triangle");
使用ApplicationContext:
ApplicationContext context = new ClassPathXMLApplicationContext("spring.xml") Triangle triangle =(Triangle)beanFactory.getBean("triangle");
从Spring文档参考这个文档:
5.15.1 BeanFactory或ApplicationContext?
使用ApplicationContext,除非你有充分的理由不这样做。
因为ApplicationContext包含了BeanFactory的所有function,所以通常推荐在BeanFactory上使用,除了一些情况,例如在内存消耗可能非常重要的Applet中,less数额外的千字节可能会起作用。 但是,对于大多数典型的企业应用程序和系统,ApplicationContext是您想要使用的。 Spring 2.0和更高版本大量使用BeanPostProcessor扩展点(以实现代理等)。 如果只使用一个普通的BeanFactory,那么相当数量的支持(如事务和AOP)将不会生效,至less不是没有一些额外的步骤。 这种情况可能会令人困惑,因为configuration没有任何问题。
BeanFactory和ApplicationContext之间的区别:
org.springframework.beans.factory.BeanFactory和org.springframework.context.ApplicationContext接口充当IoC容器。 ApplicationContext接口是build立在BeanFactory接口之上的。 它比BeanFactory增加了一些额外的function,如与Spring的AOP的简单集成,针对Web应用程序的消息资源处理(用于I18N),事件传播,应用层特定上下文(例如WebApplicationContext)。 所以最好使用ApplicationContext而不是BeanFactory。
ApplicationContext是BeanFactory的一个大兄弟,这将提供BeanFactory提供的所有东西以及许多其他的东西。
除了标准的org.springframework.beans.factory.BeanFactory生命周期function外,ApplicationContext实现还检测和调用ApplicationContextAware bean以及ResourceLoaderAware,ApplicationEventPublisherAware和MessageSourceAware bean。
基本上我们可以用两种方式创build弹簧容器对象
- 使用BeatFactory
- 使用ApplicationContext
两者都是接口
使用实现类我们可以为spring容器创build对象
来分歧
Bean工厂
-
不支持基于Annotation的dependency injection。
-
不支持I18N
-
默认情况下它支持延迟加载
-
它不允许configuration到多个configuration文件。
例如:BeanFactory context = new XmlBeanFactory(new Resource(“applicationContext.xml”));
的ApplicationContext
-
支持基于注解的依赖注射.-@Autowired,@PreDestroy
-
支持I18N
-
其默认支持Aggresive加载。
-
它允许configuration多个configuration文件。
例如:
ApplicationContext context = new ClasspathXmlApplicationContext(“applicationContext.xml”);
在实时场景中,Spring IOC核心容器(BeanFactory)和高级J2EE容器(ApplicationContext)之间的区别如下。
-
只有在调用.getBean()方法时,BeanFactory才会为spring.xml文件(
<bean></bean>
)中提到的bean(即POJO类)创build对象,但ApplicationContext将创build所有对象在加载spring.xml文件本身的时候,在spring.xml中configuration的bean(<bean></bean>
如果它的作用域没有明确提及为“Prototype”的话)。 -
BeanFactory:(懒惰的容器,因为它只有当你从用户/主类显式调用时才为bean创build对象)
/* * Using core Container - Lazy container - Because it creates the bean objects On-Demand */ //creating a resource Resource r = (Resource) new ClassPathResource("com.spring.resources/spring.xml"); //creating BeanFactory BeanFactory factory=new XmlBeanFactory(r); //Getting the bean for the POJO class "HelloWorld.java" HelloWorld worldObj1 = (HelloWorld) factory.getBean("test");
ApplicationContext :(由于在加载spring.xml文件时创build所有单例bean的对象,
ApplicationContext context = new ClassPathXmlApplicationContext("com/ioc/constructorDI/resources/spring.xml");
-
从技术上讲,build议使用ApplicationContext,因为在实时应用程序中,应用程序在服务器本身启动时将创buildbean对象。 这减less了用户请求的响应时间,因为对象已经可以响应。