BeanFactory vs ApplicationContext

我是Spring框架的新手,我一直在摆弄它,并把一些样本应用放在一起,目的是评估Spring MVC在即将到来的公司项目中的使用。到目前为止,我真的很喜欢Spring MVC,它看起来很容易使用,并鼓励你编写对单元测试非常友好的类。

作为练习,我正在为我的一个示例/测试项目编写一个主方法。我不清楚的一件事是BeanFactoryApplicationContext之间的确切区别——哪个适合在哪些条件下使用?

我知道ApplicationContext扩展了BeanFactory,但如果我只是编写一个简单的主方法,我是否需要ApplicationContext提供的额外功能?ApplicationContext到底提供了什么样的额外功能?

除了回答“我应该在main()方法中使用哪个”之外,关于在这样的场景中应该使用哪个实现,是否有任何标准或指南?我的main()方法是否应该被编写成依赖于bean/应用程序配置的XML格式——这是一个安全的假设吗,还是我将用户锁定到某个特定的东西?

这个答案在web环境中会改变吗?如果我的任何类需要了解Spring,它们更可能需要ApplicationContext吗?

谢谢你的帮助。我知道很多问题都可以在参考手册中找到答案,但如果没有仔细阅读手册,我很难找到这两个接口的清晰分解以及各自的优缺点。

289552 次浏览
spring文档在3.8.1. BeanFactory还是ApplicationContext?上做得很好。 他们有一个比较表,我将发布一个片段:

Bean工厂

  • Bean实例化/布线

应用程序上下文

  • Bean实例化/布线
  • 自动BeanPostProcessor注册
  • 自动BeanFactoryPostProcessor注册
  • 方便的MessageSource访问(用于i18n)
  • ApplicationEvent出版

因此,如果您需要应用程序上下文端显示的任何点,您应该使用ApplicationContext。

为了补充Miguel Ping回答的问题,下面是文档中的另一部分,它也回答了这个问题:

简短的版本:使用ApplicationContext,除非你有很好的理由不这样做。对于那些想要更深入地了解上述建议的“但是为什么”的人,请继续阅读。

(将这篇文章发布给未来可能会读到这个问题的春季新手)

在大多数情况下,首选ApplicationContext,除非需要节省资源,比如在移动应用程序上。

我不确定是否依赖于XML格式,但我非常确定ApplicationContext最常见的实现是XML实现,例如ClassPathXmlApplicationContext、XmlWebApplicationContext和FileSystemXmlApplicationContext。我只用过这三个。

如果您正在开发web应用程序,可以肯定地说,您将需要使用XmlWebApplicationContext。

如果您希望bean能够感知Spring,您可以让它们为此实现BeanFactoryAware和/或ApplicationContextAware,因此您可以使用BeanFactory或ApplicationContext并选择实现哪个接口。

我认为最好总是使用ApplicationContext,除非您像其他人所说的那样处于移动环境中。ApplicationContext有更多的功能,你肯定想使用postprocessor,比如RequiredAnnotationBeanPostProcessor, AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor,这将帮助你简化你的Spring配置文件,你可以在你的bean中使用@Required, @PostConstruct, @Resource等注释。

即使您不使用ApplicationContext提供的所有东西,最好还是使用它,然后如果您决定使用一些资源东西,如消息或post处理器,或其他模式来添加事务通知等,您将已经拥有一个ApplicationContext,而不需要更改任何代码。

如果你在写一个独立的应用程序,加载ApplicationContext在主方法中,使用ClassPathXmlApplicationContext,并得到主豆和调用它的运行()(或其他方法)来启动应用程序。如果您正在编写一个web应用程序,使用web . xml中的ContextLoaderListener,创造了从ServletContext ApplicationContext你稍后可以得到它,无论你使用JSP时,JSF, JSTL, struts,挂毯等。

另外,请记住,您可以使用多个Spring配置文件,您可以通过在构造函数中列出所有文件(或在ContextLoaderListener的context-param中列出它们)来创建ApplicationContext,或者您可以只加载带有import语句的主配置文件。您可以通过使用<import resource="otherfile.xml" />当您以编程方式在main方法中创建ApplicationContext并只加载一个Spring配置文件时,这是非常有用的。

  1. ApplicationContext是比BeanFactory更可取的方法

  2. 在新的Spring版本中,BeanFactoryApplicationContext取代。但是为了向后兼容,BeanFactory仍然存在

  3. ApplicationContext extends BeanFactory,有以下好处
    • 它支持文本消息的国际化
    • 它支持将事件发布到已注册的侦听器
    • 访问资源,如url和文件
    • 李< / ul > < / >

对我来说,选择BeanFactory而不是ApplicationContext的主要区别似乎是ApplicationContext将预先实例化所有的bean。从Spring文档:

Spring尽可能晚地设置属性并解析依赖项,即当bean实际创建时。这意味着,如果在创建对象或其依赖项时出现问题,那么正确加载的Spring容器稍后可以在请求对象时生成异常。例如,由于缺少或无效的属性,bean会抛出异常。这可能会延迟一些配置问题的可见性,这就是为什么ApplicationContext实现默认预实例化单例bean的原因。在实际需要这些bean之前创建这些bean需要花费一些前期时间和内存,因此您可以在创建ApplicationContext时发现配置问题,而不是在创建ApplicationContext之后。您仍然可以重写这个默认行为,这样单例bean就会延迟初始化,而不是预先实例化。

鉴于此,我最初选择BeanFactory用于集成/性能测试,因为我不想加载整个应用程序来测试孤立的bean。然而——如果我说错了,有人会纠正我——BeanFactory不支持classpath XML配置。所以BeanFactoryApplicationContext都提供了我想要的一个关键特性,但两者都没有。

据我所知,文档中关于覆盖默认实例化行为的说明发生在配置中,而且它是每个bean的,所以我不能在XML文件中设置“lazy-init”属性,否则我就不得不维护一个版本用于测试,另一个版本用于部署。

我最终所做的是扩展ClassPathXmlApplicationContext以惰性加载bean以在测试中使用,如下所示:

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);
}
}


}

参考Spring Docs中的这个文档:

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

5.15.1 bean工厂还是应用上下文?

使用ApplicationContext,除非你有很好的理由不这样做。

因为ApplicationContext包含了BeanFactory的所有功能,所以通常建议使用它而不是BeanFactory,除非在一些情况下,例如在Applet中,内存消耗可能非常大,额外的几kb可能会产生不同的结果。然而,对于大多数典型的企业应用程序和系统,ApplicationContext是您想要使用的。Spring 2.0及其后续版本大量使用了BeanPostProcessor扩展点(以实现代理等等)。如果您只使用普通的BeanFactory,那么相当数量的支持(如事务和AOP)将不起作用,至少如果没有一些额外的步骤,是不会起作用的。这种情况可能令人困惑,因为配置实际上没有任何问题。

< >强ApplicationContext: 它加载spring配置文件中配置的spring bean,并在CONTAINER启动时管理spring bean的生命周期。它不会等到“springbeanref”getBean ()被调用

< >强BeanFactory 它加载spring配置文件中配置的spring bean,在调用“springbeanref”getBean ()时管理spring bean的生命周期。因此,当我们在spring bean生命周期开始时调用“springbeanref”getBean ()时。< / p >

ApplicationContext是BeanFactory的老大哥,这将是BeanFactory提供的所有东西,还有许多其他的东西。

除了标准的org.springframework.beans.factory.BeanFactory生命周期功能外,ApplicationContext实现检测和 调用ApplicationContextAware bean以及ResourceLoaderAware、ApplicationEventPublisherAware和MessageSourceAware bean

Bean工厂与应用上下文来源:spring文档的特征矩阵

enter image description here

beanfactory和ApplicationContext功能的截图

BeanFactoryApplicationContext都是从spring 国际奥委会容器中获取bean的方法,但仍有一些区别。

BeanFactory是实例化、配置和管理许多bean的实际容器。这些bean通常彼此协作,因此它们之间存在依赖关系。这些依赖关系反映在BeanFactory使用的配置数据中。

BeanFactoryApplicationContext都是Java接口,ApplicationContext扩展了BeanFactory。它们都是使用XML配置文件进行配置的。简而言之,BeanFactory提供了基本的控制反转(国际奥委会)和依赖注入()特性,而ApplicationContext提供了先进的特性。

BeanFactory由接口“org.springframework.beans.factory”表示,其中BeanFactory有多个实现。

ClassPathResource resource = new ClassPathResource("appConfig.xml");
XmlBeanFactory factory = new XmlBeanFactory(resource);

区别

  1. BeanFactory实例化bean,当你调用getBean()方法时,同时ApplicationContext实例化单例bean,当容器启动时,它不会等待getBean()被调用。

  2. BeanFactory不支持国际化,但ApplicationContext支持国际化。

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

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

  5. 如果您正在使用自动布线和使用BeanFactory,那么您需要注册AutoWiredBeanPostProcessor使用API,如果您正在使用ApplicationContext,您可以在XML中配置。总之,BeanFactory可以用于测试和非生产用途,但ApplicationContext是功能更丰富的容器实现,应该比BeanFactory更受欢迎

  6. BeanFactory默认支持它Lazy加载和ApplicationContext默认支持 aggressive 加载。

基本上我们可以用两种方式创建spring容器对象

  1. 使用BeanFactory。
  2. 使用ApplicationContext。

都是界面,

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

来看看区别

BeanFactory:

  1. 不支持基于注释的依赖注入。

  2. 不支持I18N。

  3. 默认情况下,它支持惰性加载。

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

ex: BeanFactory context=new XmlBeanFactory(new Resource("applicationContext.xml"));

ApplicationContext

  1. 支持基于注释的依赖注入。@ autowired, @PreDestroy

  2. I18N支持

  3. 它默认支持侵略性加载。

  4. 它允许配置多个配置文件。

< p >, < br >

. ApplicationContext context=new ClasspathXmlApplicationContext(" ApplicationContext .xml")

Spring提供了两种IOC容器,一个是XMLBeanFactory,另一个是ApplicationContext

BeanFactory ApplicationContext
注释支持 没有 是的
BeanPostProcessor登记 手册 自动
实现 XMLBeanFactory 类路径/文件系统/ WebXmlApplicationContext
国际化 没有 是的
企业服务 没有 是的
ApplicationEvent出版 没有 是的

enter image description here

  • FileSystemXmlApplicationContext通过完整路径加载的bean。
  • ClassPathXmlApplicationContext通过CLASSPATH加载的bean
  • XMLWebApplicationContextAnnotationConfigWebApplicationContext bean通过web应用程序上下文加载。
  • 从基于Annotation的配置中加载Spring bean。

例子:

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeansConfiguration.class);
  • ApplicationContext是由web.xml中定义的ContextLoaderListenerContextLoaderServletstruts-config.xml中定义的ContextLoaderPlugin初始化的容器。

请注意: XmlBeanFactory从Spring 3.1开始是弃用,而不是DefaultListableBeanFactoryXmlBeanDefinitionReader

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

  1. 只有当你调用. getbean()方法时,BeanFactory才会为spring.xml文件(<bean></bean>)中提到的bean(即POJO类)创建对象,但是ApplicationContext在加载spring.xml文件本身时为spring.xml中配置的所有bean (<bean></bean>,如果它的作用域没有显式地提到为“Prototype”)创建对象。

  2. BeanFactory:(惰性容器,因为它只在从用户/主类显式调用时才为bean创建对象)

    /*
    * 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文件本身时创建了所有单例bean的对象)

    ApplicationContext context = new ClassPathXmlApplicationContext("com/ioc/constructorDI/resources/spring.xml");
    
  3. Technically, using ApplicationContext is recommended because in real-time applications, the bean objects will be created while the application is getting started in the server itself. This reduces the response time for the user request as the objects are already available to respond.

a. bean工厂和应用程序上下文之间的一个区别是前者只在调用getBean()方法时实例化bean,而ApplicationContext在容器启动时实例化单例bean,它不等待getBean被调用。

b。

ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");

ApplicationContext context = new ClassPathXmlApplicationContext{"spring_dao.xml","spring_service.xml};

您可以根据项目需求使用一个或多个xml文件。我在这里使用了两个xml文件,即一个用于服务类的配置细节,另一个用于dao类。这里ClassPathXmlApplicationContext是ApplicationContext的子。

c. BeanFactory Container是基本容器,它只能创建对象和注入依赖项。但我们不能附加其他服务,如安全、事务、消息等,以提供我们必须使用ApplicationContext容器的所有服务。

d. BeanFactory不提供国际化支持,即i18n,但ApplicationContext提供了国际化支持。

e. BeanFactory容器不支持自动扫描(支持基于注释的依赖注入)特性,但ApplicationContext容器支持。

f.直到请求时间,Beanfactory容器才会创建bean对象。这意味着Beanfactory容器会懒惰地装载bean。而ApplicationContext容器只在加载时创建单例bean的对象。这意味着有早期装载。

g. Beanfactory容器只支持两个作用域(singleton &豆子的原型)。但是ApplicationContext容器支持所有的bean范围。

BeanFactoryApplicationContext的区别如下:

  1. BeanFactory使用惰性初始化 ApplicationContext使用主动初始化。对于BeanFactory, bean是在调用getBeans()方法时创建的,但是对于ApplicationContext, bean是在创建ApplicationContext对象时预先创建的。
  2. BeanFactory使用语法 ApplicationContext显式地提供了一个资源对象,它自己创建和管理资源对象。
  3. abc0 ApplicationContext支持国际化。
  4. 在BeanFactory中,不支持基于注释的依赖注入。

使用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)context.getBean("triangle");

我认为值得一提的是,自Spring 3以来,如果你想创建一个工厂,你也可以使用@configuration注释结合适当的@scope

@Configuration
public class MyFactory {


@Bean
@Scope("prototype")
public MyClass create() {
return new MyClass();
}
}

使用@ComponentScan注释或xml配置的Spring容器应该可以看到你的工厂

Spring bean scope article from baeldung site

在非web应用程序中使用BeanFactory,因为它只支持单例和原型bean作用域。

而ApplicationContext容器确实支持所有的bean作用域,所以你应该将它用于web应用程序。

总而言之:

ApplicationContext包含BeanFactory的所有功能。 一般建议使用前者。< / p >

在一些有限的情况下,例如在移动应用程序中,内存消耗可能是关键的。

在这种情况下,使用更轻量级的BeanFactory是合理的。然而,在大多数企业应用程序中,ApplicationContext是你想要使用的。

要了解更多,请参阅我的博客文章:

BeanFactory和ApplicationContext在Spring中的区别- java Spring博客的基础

我需要解释一下BeanFactory &ApplicationContext。

BeanFactory: BeanFactory是访问SpringBean容器的根接口。bean容器有一个基本的客户端视图。 该接口由对象类实现,该对象类包含bean定义的数量,并且每个定义都由String名称
唯一标识 根据Bean定义,工厂将返回实例,该实例可能是包含对象的实例,也可能是单个共享实例。返回哪种类型的实例取决于bean工厂的配置 通常Bean工厂会加载所有的Bean定义,这些定义存储在配置源中,比如XML…< / p >

BeanFactory是一个为依赖注入提供基本支持的最简单的容器

<强>应用程序上下文 应用程序上下文是spring应用程序中的一个中心接口,它向应用程序提供配置信息。它实现了Bean工厂接口。< / p >

应用程序上下文是一个高级容器,它增加了高级级别的企业特定功能,例如从属性文件....解析文本消息的能力等

一个ApplicationContext提供:

用于访问应用程序组件的Bean工厂方法。继承自ListableBeanFactory。 以通用方式加载文件资源的能力。继承自ResourceLoader接口。 向已注册的侦听器发布事件的能力。继承自ApplicationEventPublisher接口。 能够解析消息,支持国际化。继承自MessageSource接口。 从父上下文继承。后代上下文中的定义总是优先级。这意味着,例如,一个单一的父上下文可以被整个web应用程序使用,而每个servlet都有自己独立于任何其他servlet的子上下文。 除了标准的BeanFactory生命周期功能外,ApplicationContext实现还检测和调用ApplicationContextAware bean以及ResourceLoaderAware、ApplicationEventPublisherAware和MessageSourceAware bean

BeanFactory表示在运行时调用getBean ()方法后,由懒洋洋地实例化bean对象的spring容器。

ApplicationContext表示spring框架,其中急切地在部署时实例化bean对象,而不在运行时调用getBean ()方法。

我的六个美分:

  1. BeanFactoryApplicationContext都是__abc9,其中ApplicationContext扩展了BeanFactory。所以ApplicationContext是一个ApplicationContext0接口,而BeanFactoryApplicationContext1接口。换句话说,ApplicationContext具有BeanFactory的所有特征,并且它具有一些ApplicationContext2,这些在BeanFactory中是不存在的。
  2. BeanFactory按需加载bean,即延迟加载,而ApplicationContext在启动时加载所有bean,即立即加载
  3. BeanFactory不支持注释,而ApplicationContext支持注释。
  4. ApplicationContext具有在BeanFactory: 国际化、事件发布、AOP特性中不存在的附加功能
  5. BeanFactory只支持两个__abc2——单例原型,而ApplicationContext支持所有的bean作用域。
  6. BeanFactory不会注册BeanFactoryPostProcessorBeanPostProcessor 自动,而ApplicationContext会自动注册它们。