BeanFactory与ApplicationContext

我对Spring Framework相当陌生,为了评估Spring MVC在即将到来的公司项目中的使用,我一直在玩弄它,并将几个示例应用程序放在一起。 到目前为止,我真的很喜欢我在Spring MVC中看到的东西,看起来很容易使用,并鼓励您编写对unit testing非常友好的类。

就像一个练习,我正在为我的一个样本/testing项目写一个主要的方法。 我不清楚的一件事情是BeanFactoryApplicationContext之间的确切区别 – 适用于哪些条件?

我明白, 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。 所以BeanFactoryApplicationContext都提供了我想要的重要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新手谁可能会读这个问题)

  1. ApplicationContextBeanFactoryBeanFactory

  2. 在新的Spring版本中, BeanFactoryApplicationContextreplace。 但是BeanFactory仍然存在向后兼容性

  3. 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 | +---------------------------------------+-----------------+--------------------------------+ 

在这里输入图像说明

  1. FileSystemXmlApplicationContext:通过完整path加载的Bean。
  2. ClassPathXmlApplicationContext:通过CLASSPATH加载的Bean
  3. 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实现哪个接口。

BeanFactoryApplicationContext都是从你的spring IOC容器获取bean的方法,但是仍然有一些不同。

BeanFactory是实例化,configuration和pipe理一些bean的实际容器。 这些bean通常是相互协作的,因此彼此之间有依赖关系。 这些依赖关系反映在BeanFactory使用的configuration数据中。

BeanFactoryApplicationContext都是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); 

区别

  1. 调用getBean()方法时, BeanFactory实例化bean,而Container启动时ApplicationContext实例化Singleton bean,它不会等待getBean()被调用。

  2. BeanFactory不支持国际化,但ApplicationContext提供对它的支持。

  3. BeanFactoryApplicationContext之间的另一个区别是能够将事件发布到注册为侦听器的bean。

  4. BeanFactory接口的stream行实现之一是XMLBeanFactory,ApplicationContext接口的stream行实现之一是ClassPathXmlApplicationContext

  5. 如果您正在使用自动连线并使用BeanFactory ,那么您需要使用API​​注册AutoWiredBeanPostProcessor ,如果您使用的是ApplicationContext,则可以使用API​​进行configuration。 总结BeanFactory可以用于testing和非生产用途,但ApplicationContext是更多特性丰富的容器实现,应该比BeanFactory更受青睐

  6. 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作用域。

BeanFactoryApplicationContext之间的区别如下:

  1. BeanFactory使用延迟初始化, ApplicationContext使用预先初始化。 在BeanFactory的情况下,在调用getBeans()方法时创buildbean,但在创buildApplicationContext对象时,在ApplicationContext的情况下创buildbean。
  2. BeanFactory使用语法显式地提供资源对象, 但是 ApplicationContext自己创build和pipe理资源对象。
  3. BeanFactory不支持国际化, ApplicationContext支持国际化。
  4. 不支持基于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文档参考这个文档:

http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/beans.html#context-introduction-ctx-vs-beanfactory

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弹簧容器对象

  1. 使用BeatFactory
  2. 使用ApplicationContext

两者都是接口

使用实现类我们可以为spring容器创build对象

来分歧

Bean工厂

  1. 不支持基于Annotation的dependency injection。

  2. 不支持I18N

  3. 默认情况下它支持延迟加载

  4. 它不允许configuration到多个configuration文件。

例如:BeanFactory context = new XmlBeanFactory(new Resource(“applicationContext.xml”));

的ApplicationContext

  1. 支持基于注解的依赖注射.-@Autowired,@PreDestroy

  2. 支持I18N

  3. 其默认支持Aggresive加载。

  4. 它允许configuration多个configuration文件。

例如:
ApplicationContext context = new ClasspathXmlApplicationContext(“applicationContext.xml”);

在实时场景中,Spring IOC核心容器(BeanFactory)和高级J2EE容器(ApplicationContext)之间的区别如下。

  1. 只有在调用.getBean()方法时,BeanFactory才会为spring.xml文件( <bean></bean> )中提到的bean(即POJO类)创build对象,但ApplicationContext将创build所有对象在加载spring.xml文件本身的时候,在spring.xml中configuration的bean( <bean></bean>如果它的作用域没有明确提及为“Prototype”的话)。

  2. 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"); 
  3. 从技术上讲,build议使用ApplicationContext,因为在实时应用程序中,应用程序在服务器本身启动时将创buildbean对象。 这减less了用户请求的响应时间,因为对象已经可以响应。