259

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

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

我理解ApplicationContextextends BeanFactory,但如果我只是写一个简单的 main 方法,我需要ApplicationContext提供的额外功能吗?究竟提供了什么样的额外功能ApplicationContext

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

这个答案在 Web 环境中是否会发生变化 - 如果我的任何课程需要了解 Spring,他们是否更有可能需要ApplicationContext

谢谢你的帮助。我知道很多这些问题可能在参考手册中得到了解答,但是如果没有用细齿梳通读手册,我很难找到这两个接口的明确细分以及每个接口的优缺点。

4

21 回答 21

224

春季文档在这方面很棒:3.8.1。BeanFactory 还是 ApplicationContext?. 他们有一个比较表,我将发布一个片段:

豆厂

  • Bean实例化/接线

应用程序上下文

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

因此,如果您需要应用程序上下文方面提出的任何要点,您应该使用 ApplicationContext。

于 2008-10-28T14:04:37.687 回答
68

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

豆厂 应用程序上下文
注释支持 是的
BeanPostProcessor 注册 手动的 自动的
执行 XMLBeanFactory 类路径/文件系统/WebXmlApplicationContext
国际化 是的
企业服务 是的
应用事件发布 是的

在此处输入图像描述

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

例子:

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

注意:从 Spring 3.1 开始XmlBeanFactory推荐使用DefaultListableBeanFactory,而支持and XmlBeanDefinitionReader

于 2016-01-20T02:29:13.207 回答
50

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

在实际创建 bean 时,Spring 会尽可能晚地设置属性并解析依赖关系。这意味着,如果在创建该对象或其依赖项之一时出现问题,则当您请求对象时,正确加载的 Spring 容器稍后会生成异常。例如,bean 会由于缺少或无效的属性而引发异常。某些配置问题的这种潜在的延迟可见性是默认情况下 ApplicationContext 实现预实例化单例 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);
        }
    }

}
于 2010-02-28T03:04:00.640 回答
33

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

短版:使用 ApplicationContext ,除非您有充分的理由不这样做。对于那些正在寻找关于上述建议的“但为什么”的更深入的人,请继续阅读。

(为任何可能阅读此问题的未来 Spring 新手发布此信息)

于 2008-10-28T14:08:23.997 回答
20
  1. ApplicationContext是比更优选的方式BeanFactory

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

  3. ApplicationContext extends BeanFactory并具有以下好处
    • 它支持短信的国际化
    • 它支持向注册的侦听器发布事件
    • 访问 URL 和文件等资源
于 2010-02-27T12:04:16.480 回答
14

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

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

于 2013-06-04T07:15:46.687 回答
13

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

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

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

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

于 2008-11-04T18:39:56.563 回答
9

BeanFactoryApplicationContext的区别如下:

  1. BeanFactory 使用延迟初始化,但ApplicationContext 使用急切初始化。在 BeanFactory 的情况下,bean 是在您调用 getBeans() 方法时创建的,但在 ApplicationContext 的情况下,bean 是在创建 ApplicationContext 对象时预先创建的。
  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 context = new ClassPathXMLApplicationContext("spring.xml")
Triangle triangle =(Triangle)context.getBean("triangle");
于 2017-10-01T16:19:46.730 回答
6

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

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

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

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

于 2008-10-28T21:02:39.840 回答
6

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

  1. 使用 BeanFactory。
  2. 使用应用程序上下文。

两者都是接口,

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

来到差异

豆工厂:

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

  2. 不支持 I18N。

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

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

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

应用程序上下文

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

  2. 支持I18N

  3. 它默认支持积极加载。

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

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

于 2016-01-18T05:59:53.177 回答
5

Bean Factory 与 Application Context 的特征矩阵来自 spring 文档

在此处输入图像描述

BeanFactry 和 ApplicationContext 的特性截图

于 2015-06-30T13:30:38.973 回答
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. BeanFactory在调用getBean()方法时实例化 bean,而 ApplicationContext 在容器启动时实例化 Singleton bean,它不会等待调用 getBean()。

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

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

  4. BeanFactory接口的流行实现之一是XMLBeanFactoryApplicationContext接口的流行实现之一是ClassPathXmlApplicationContext

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

  6. BeanFactory默认支持延迟加载,ApplicationContext默认支持Aggressive加载。

于 2016-01-15T05:32:19.863 回答
4

一种。bean factory 和 application context 之间的一个区别是前者仅在您调用 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 类。这里 ClassPathXmlApplicationContext 是 ApplicationContext 的子级。

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

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

e. BeanFactory Container 不支持 AutoScanning (Support Annotation based dependency Injection) 的特性,但 ApplicationContext Container 支持。

F。Beanfactory Container 在请求时间之前不会创建 bean 对象。这意味着 Beanfactory Container 会延迟加载 bean。而 ApplicationContext Container 仅在加载时创建 Singleton bean 的对象。这意味着有早期加载。

G。Beanfactory Container 仅支持 bean 的两个范围(单例和原型)。但是 ApplicationContext Container 支持所有的 beans 范围。

于 2017-01-06T15:04:33.013 回答
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 中内存消耗可能很关键并且额外的几 KB 可能会产生影响。但是,对于大多数典型的企业应用程序和系统,ApplicationContext 是您想要使用的。Spring 2.0 及更高版本大量使用 BeanPostProcessor 扩展点(以实现代理等)。如果你只使用一个普通的 BeanFactory,诸如事务和 AOP 之类的相当多的支持将不会生效,至少在你没有一些额外步骤的情况下不会生效。这种情况可能会令人困惑,因为配置实际上没有任何问题。

于 2013-04-27T16:58:43.900 回答
1

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

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

于 2015-02-26T06:52:30.917 回答
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 中配置为“原型”。

  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 对象将在应用程序在服务器本身启动时创建。这减少了用户请求的响应时间,因为对象已经可以响应。

于 2016-02-26T01:19:40.357 回答
1

我需要解释 BeanFactory 和 ApplicationContext。

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

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

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

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

ApplicationContext 提供:

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

于 2020-03-06T07:45:08.923 回答
0

我认为值得一提的是,从 Spring 3 开始,如果要创建工厂,还可以使用@configuration注解结合适当的@scope

@Configuration
public class MyFactory {

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

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

来自 baeldung 网站的 Spring bean scopes 文章

于 2018-01-23T13:00:10.750 回答
0

对非 Web 应用程序使用 BeanFactory,因为它只支持 Singleton 和 Prototype bean-scopes。

虽然 ApplicationContext 容器确实支持所有 bean-scopes,但您应该将它用于 Web 应用程序。

于 2018-04-21T22:01:44.707 回答
0

总之:

ApplicationContext包括 BeanFactory 的所有功能。一般推荐使用前者。

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

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

更多内容请看我的博文:

Spring中BeanFactory和ApplicationContext的区别——来自基础的java spring博客

于 2018-07-07T17:25:12.657 回答
0

BeanFactory是指 Spring 容器,它在运行时调用getBean()方法后延迟实例化 bean 对象。

ApplicationContext是指 spring 框架,它在部署期间急切地实例化 bean 对象,而在运行时不调用 getBean() 方法或在此之前调用getBean()方法。

于 2021-06-28T15:25:56.430 回答