BeanFactory与ApplicationContext


235

我对Spring Framework还是很陌生,我一直在使用它,并将一些示例应用程序放在一起,以评估Spring MVC以便在即将到来的公司项目中使用。到目前为止,我非常喜欢我在Spring MVC中看到的内容,它似乎非常易于使用,并鼓励您编写对单元测试非常友好的类。

作为练习,我正在为我的一个样本/测试项目编写一种主要方法。我不清楚的一件事是BeanFactory和之间的确切区别ApplicationContext-在哪种情况下适合使用?

我知道可以ApplicationContext扩展BeanFactory,但是如果我只是编写一个简单的main方法,是否需要ApplicationContext提供的额外功能?究竟提供什么样的额外功能ApplicationContext

除了回答“我应该在main()方法中使用哪个”之外,在这种情况下应该使用哪种实现还有任何标准或准则?是否应该将main()方法编写为依赖于XML格式的bean /应用程序配置-这是一个安全的假设,还是我将用户锁定在特定的位置?

并且此答案在Web环境中是否会更改-如果我的任何一个类需要了解Spring,是否更有可能需要它们ApplicationContext

谢谢你的帮助。我知道参考手册中可能会回答很多这样的问题,但是我很难找到这两个接口以及每个接口的优缺点的清晰细目,而没有用细齿梳子通读手册。

Answers:


209

spring文档在以下方面很棒:3.8.1。BeanFactory或ApplicationContext?。他们有一张带有比较表,我将发布一个片段:

豆工厂

  • Bean实例化/接线

应用环境

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

因此,如果需要在“应用程序上下文”侧显示的任何要点,则应使用ApplicationContext。


3
BeanFactory是轻量级的,但是如果您要“真正”使用Spring,则不妨使用ApplicationContext:如果不使用其高级功能,则涉及的开销很少,但是它们仍然可用如果/何时使用它们。
MetroidFan2002

2
您说“自动BeanPostPorcessor重新注册”是什么意思?这是否意味着该类不必实现该接口?
阿比迪2014年

2
ApplicationContext支持针对BeanFactory的AOP。
ininprsr

1
有了BeanFactory我们,我们可以动态传递构造函数参数,但ApplicationContext不能这样做。
Half Blood Prince

1
链接的Spring文档中的重要说明:“ Spring 2.0及更高版本的版本大量使用了BeanPostProcessor扩展点(以实现代理等功能),如果您仅使用普通的BeanFactory,则将获得大量支持,例如事务而且AOP不会生效(至少没有您采取一些额外措施的话)。”
mark.monteiro '18

52

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

+---------------------------------------+-----------------+--------------------------------+
|                                       | BeanFactory     |       ApplicationContext       |
+---------------------------------------+-----------------+--------------------------------+
| Annotation support                    | No              | Yes                            |
| BeanPostProcessor Registration        | Manual          | Automatic                      |
| implementation                        | XMLBeanFactory  | ClassPath/FileSystem/WebXmlApplicationContext|
| internationalization                  | No              | Yes                            |
| Enterprise services                   | No              | Yes                            |
| ApplicationEvent publication          | No              | Yes                            |
+---------------------------------------+-----------------+--------------------------------+

在此处输入图片说明

  • FileSystemXmlApplicationContext 通过完整路径加载的Bean。
  • ClassPathXmlApplicationContext 通过CLASSPATH加载的Bean
  • XMLWebApplicationContextAnnotationConfigWebApplicationContext通过Web应用程序上下文加载的bean。
  • AnnotationConfigApplicationContext 从基于注释的配置加载Spring bean。

例:

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeansConfiguration.class);
  • ApplicationContext是由初始化的容器ContextLoaderListenerContextLoaderServlet以限定的web.xmlContextLoaderPlugin所限定struts-config.xml

XmlBeanFactory弃用如春3.1赞成的DefaultListableBeanFactoryXmlBeanDefinitionReader


2
图中的ClassPathXmlApplicationContext下方的AnnotationConfigApplicationContext不是-AnnotationConfigWebApplicationContext-
Akhil Jain

48

对我来说,最主要的区别,选择BeanFactoryApplicationContext似乎是ApplicationContext将预实例所有的豆类。从春天文档

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

鉴于此,我最初选择BeanFactory用于集成/性能测试,因为我不想加载整个应用程序来测试隔离的bean。但是-如果我错了,有人纠正了我- BeanFactory不支持classpathXML配置。因此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);
        }
    }

}

2
我认为,如果您的单元测试正在加载整个Spring上下文,那么它们不是“单元测试”,而是集成测试。
matt b'3

1
好点子。以我为例,我实际上需要从上下文中加载bean以进行性能和集成测试,并且出于习惯写了“单元测试”。我已经相应地编辑了答案。
Lyle 2010年

2
BeanFactory doesn't support classpath XML configuration.我认为它:stackoverflow.com/questions/5231371/...
复刻骑自行车的

29

要添加Miguel Ping回答的内容,以下是文档另一部分也回答了这一问题:

简短版本:除非您有充分的理由不这样做,否则请使用ApplicationContext。对于那些希望对上述建议的“但为何”有更多了解的人,请继续阅读。

(将其发布给将来可能会阅读此问题的任何春季新手)


19
  1. ApplicationContextBeanFactory

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

  3. ApplicationContext extends BeanFactory 并具有以下优点
    • 它支持短信的国际化
    • 它支持向注册的侦听器发布事件
    • 访问诸如URL和文件之类的资源

13

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

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


12

我认为最好始终使用ApplicationContext,除非您已经在其他人已经说过的移动环境中使用。ApplicationContext具有更多功能,您肯定要使用PostProcessor,例如RequiredAnnotationBeanPostProcessor,AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor,这将帮助您简化Spring配置文件,并且可以在bean中使用@ Required,@ PostConstruct,@ Resource等批注。 。

即使您没有使用ApplicationContext提供的所有东西,还是还是要使用它,然后再决定是否使用某些资源的东西(例如消息或后处理器)或其他架构来添加事务性建议,这样,将已经有一个ApplicationContext并且不需要更改任何代码。

如果要编写独立的应用程序,请使用ClassPathXmlApplicationContext在主方法中加载ApplicationContext,并获取主bean并调用其run()(或任何方法)以启动应用程序。如果您正在编写Web应用程序,请在web.xml中使用ContextLoaderListener,以便它创建ApplicationContext,并且以后可以从ServletContext中获取它,而不管是否使用JSP,JSF,JSTL,struts,Tapestry等。 。

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


6

在大多数情况下,除非需要像在移动应用程序上那样节省资源,否则首选ApplicationContext。

我不确定是否依赖XML格式,但是我可以肯定ApplicationContext的最常见实现是XML,例如ClassPathXmlApplicationContext,XmlWebApplicationContext和FileSystemXmlApplicationContext。那是我用过的仅有的三个。

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

如果您希望bean知道Spring,可以让它们实现BeanFactoryAware和/或ApplicationContextAware,因此可以使用BeanFactory或ApplicationContext并选择要实现的接口。


这是文档中的相关部分,因为ApplicationContext包含的所有功能BeanFactory,所以通常建议优先使用BeanFactory,除非在少数情况下(例如),在这种情况下Applet,内存消耗可能很关键,可能会增加几千字节做出改变。但是,对于大多数“典型”企业应用程序和系统,ApplicationContext您将要使用。
M. Atif Riaz 2014年

6

BeanFactoryApplicationContext之间的区别如下:

  1. BeanFactory使用延迟初始化,但是 ApplicationContext使用热切初始化。对于BeanFactory,在调用getBeans()方法时将创建bean,但是在创建ApplicationContext对象时,将在ApplicationContext的情况下首先创建bean。
  2. BeanFactory使用语法显式提供资源对象,但是 ApplicationContext自己创建和管理资源对象。
  3. BeanFactory不支持国际化, ApplicationContext支持国际化。
  4. 使用BeanFactory时,不支持基于注释的依赖项注入,在ApplicationContext中支持基于注释的依赖项注入。

使用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");

5

BeanFactoryApplicationContext都是从Spring IOC容器中获取bean的方法,但是仍然存在一些差异。

BeanFactory是实际的容器,用于实例化,配置和管理许多Bean。这些bean通常相互协作,因此彼此之间具有依赖性。这些依赖关系反映在BeanFactory使用的配置数据中。

BeanFactoryApplicationContext都是Java接口,ApplicationContext扩展了BeanFactory。它们都是使用XML配置文件进行配置。简而言之,BeanFactory提供了基本的控制反转(IoC)和依赖注入(DI)功能,而ApplicationContext提供了高级功能。

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

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

区别

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

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

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

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

  5. 如果您使用自动接线并使用BeanFactory,则需要使用API 注册AutoWiredBeanPostProcessor,如果您使用ApplicationContext,则可以在XML中进行配置 。总结BeanFactory可以用于测试和非生产使用,但是ApplicationContext是功能更丰富的容器实现,应该比BeanFactory更受青睐

  6. BeanFactory默认情况下支持延迟加载,而ApplicationContext默认情况下支持Aggresive加载。


您能更清楚地解释一下#1吗,如果我在spring config文件中定义了一个singleton bean,那么spring容器将创建一个singleton bean,不管那里是BeanFactory还是ApplicationContext都有什么关系。
pjj


3

一个。bean工厂和应用程序上下文之间的区别是,前者仅在您调用getBean()方法时实例化bean,而ApplicationContext在容器启动时实例化Singleton 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容器是基本容器,它只能创建对象和注入依赖项。但是我们不能附加其他服务,例如安全性,事务,消息传递等,以提供我们必须使用ApplicationContext Container的所有服务。

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

e。BeanFactory容器不支持自动扫描功能(基于支持注释的依赖项注入),但是ApplicationContext容器支持。

F。直到请求时间,Beanfactory Container才会创建Bean对象。这意味着Beanfactory Container会延迟加载bean。虽然ApplicationContext Container仅在加载时创建Singleton bean的对象。这意味着有早期加载。

G。Beanfactory容器仅支持Bean的两个作用域(单个和原型)。但是ApplicationContext Container支持所有bean范围。


点a和f相同。可以结合在一起。
dhana1310

3

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

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

都是接口

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

差异化

BeanFactory:

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

  2. 不支持I18N。

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

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

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

ApplicationContext

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

  2. 支持I18N

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

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

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


1

从Spring Docs引用此文档:

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的所有功能,所以通常建议在BeanFactory上使用它,但在某些情况下(例如在Applet中,内存消耗可能很关键,而额外的几千字节可能会有所作为)。但是,对于大多数典型的企业应用程序和系统,您将要使用ApplicationContext。Spring 2.0和更高版本大量使用了BeanPostProcessor扩展点(以实现代理等)。如果仅使用普通的BeanFactory,那么诸如事务和AOP之类的大量支持将不会生效,至少在您没有采取一些额外步骤的情况下也是如此。这种情况可能会造成混乱,因为配置实际上并没有错。


1

ApplicationContext是BeanFactory的哥哥,这将为BeanFactory提供的所有东西以及许多其他东西。

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


1

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

  1. <bean></bean>仅当调用.getBean()方法时,BeanFactory才会为spring.xml文件()中提到的bean创建对象(即,为POJO类),而ApplicationContext为所有bean创建对象(<bean></bean>如果其作用域不是在加载spring.xml文件本身时,在spring.xml中配置为显式提及的“ 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. 从技术上讲,建议使用ApplicationContext,因为在实时应用程序中,将在服务器本身启动应用程序时创建Bean对象。由于对象已经可用于响应,因此这减少了用户请求的响应时间。


Stack Overflow不是论坛,因此,我对您的答案进行了编辑,以更直接地回答问题并避免引起讨论。
Jeffrey Bosboom '16


0

不要将BeanFactory用于非Web应用程序,因为它仅支持Singleton和Prototype bean范围。

尽管ApplicationContext容器确实支持所有bean范围,所以您应该将其用于Web应用程序。


0

综上所述:

ApplicationContext的包括了BeanFactory所有的功能。通常建议使用前者。

在某些情况下(例如在移动应用程序中),内存消耗可能至关重要。

在那种情况下,使用轻量级的BeanFactory是合理的。但是,在大多数企业应用程序中,将要使用ApplicationContext

有关更多信息,请参见我的博客文章:

Spring中BeanFactory和ApplicationContext之间的区别–来自基础知识的Java Spring博客


0

我需要解释BeanFactory和ApplicationContext。

BeanFactory: BeanFactory是用于访问SpringBean Container的根接口.bean容器有基本的客户端视图。该接口由保存多个Bean定义的对象类实现,并且每个类均由字符串名称唯一标识。
根据Bean定义,工厂将返回实例,该实例可以是所包含对象的实例,也可以是单个共享实例。将返回哪种类型的实例取决于bean工厂的配置。
通常,Bean工厂将加载所有的所有bean定义,这些定义存储在XML ...等配置源中。

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

应用环境 应用程序上下文是spring应用程序中的一个中央接口,向应用程序提供配置信息。它实现了Bean Factory接口。

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

ApplicationContext提供:

用于访问应用程序组件的Bean工厂方法。继承自ListableBeanFactory。以通用方式加载文件资源的能力。继承自ResourceLoader接口。将事件发布给注册的侦听器的能力。继承自ApplicationEventPublisher接口。解决消息的能力,支持国际化。继承自MessageSource接口。从父上下文继承。在后代上下文中的定义将始终优先。例如,这意味着整个Web应用程序都可以使用单个父上下文,而每个servlet都有其自己的子上下文,该子上下文独立于任何其他servlet的子上下文。除了标准的BeanFactory生命周期功能之外,

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.