【问题标题】:BeanFactory vs ApplicationContextBeanFactory 与 ApplicationContext
【发布时间】:2010-09-19 14:14:31
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

    标签: spring managed-bean applicationcontext


    【解决方案1】:

    春季文档在这方面做得很好:3.8.1. BeanFactory or ApplicationContext?。 他们有一个比较表,我会发布一个sn-p:

    豆厂

    • Bean 实例化/接线

    应用程序上下文

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

    因此,如果您需要 Application Context 方面提出的任何要点,您应该使用 ApplicationContext。

    【讨论】:

    • BeanFactory 是轻量级的,但如果您要“真正”使用 Spring,您不妨使用 ApplicationContext:如果您不使用它的花哨,所涉及的开销很少功能,但如果/当您使用它们时,它们仍然可用。
    • “自动BeanPostPorcessor注册”是什么意思?这是否意味着该类不必实现该接口?
    • ApplicationContext 支持针对 BeanFactory 的 AOP。
    • 使用BeanFactory,我们可以动态传递构造函数参数,但使用ApplicationContext,我们不能这样做。
    • 来自链接的 Spring 文档的重要说明:“Spring 2.0 及更高版本大量使用 BeanPostProcessor 扩展点(以实现代理等),如果您仅使用普通 BeanFactory 则交易和 AOP 等相当多的支持将不会生效(至少在您没有一些额外步骤的情况下不会生效)。”
    【解决方案2】:

    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 加载的 Beans
    • XMLWebApplicationContextAnnotationConfigWebApplicationContext bean 通过 Web 应用程序上下文加载。
    • AnnotationConfigApplicationContext 从基于注解的配置中加载 Spring bean。

    示例:

    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeansConfiguration.class);
    
    • ApplicationContext 是由 ContextLoaderListenerContextLoaderServlet 中定义的 web.xmlContextLoaderPlugin 中定义的 struts-config.xml 中定义的容器。

    注意XmlBeanFactory 在 Spring 3.1 中是 deprecated,支持 DefaultListableBeanFactoryXmlBeanDefinitionReader

    【讨论】:

    • 它的AnnotationConfigApplicationContext 不是-AnnotationConfigWebApplicationContext- 图中ClassPathXmlApplicationContext 下面
    • 感谢比喻性的解释。这有帮助!
    【解决方案3】:

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

    在实际创建 bean 时,Spring 会尽可能晚地设置属性并解析依赖关系。这意味着,如果在创建该对象或其依赖项之一时出现问题,则当您请求对象时,正确加载的 Spring 容器稍后会生成异常。例如,bean 会由于缺少或无效的属性而引发异常。某些配置问题的这种潜在延迟可见性是为什么 ApplicationContext 实现默认预实例化单例 bean。以在实际需要之前创建这些 bean 的一些前期时间和内存为代价,您会在创建 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 上下文,它们不是“单元测试”,而是集成测试。
    • 好点。在我的情况下,我实际上需要从上下文中加载 bean 以进行性能和集成测试,并且出于习惯编写了“单元测试”。我已经相应地编辑了我的答案。
    • BeanFactory doesn't support classpath XML configuration. 我认为可以:stackoverflow.com/questions/5231371/…
    【解决方案4】:

    为了补充 Miguel Ping 的回答,another section from the documentation 也回答了这个问题:

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

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

    【讨论】:

      【解决方案5】:
      1. ApplicationContextBeanFactory 更受欢迎

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

      3. ApplicationContext extends BeanFactory 有以下好处
        • 支持短信国际化
        • 它支持向注册的侦听器发布事件
        • 访问 URL 和文件等资源

      【讨论】:

        【解决方案6】:

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

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

        【讨论】:

          【解决方案7】:

          我认为始终使用 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,或者您可以只加载一个主配置具有导入语句的文件。您可以使用 将 Spring 配置文件导入另一个 Spring 配置文件,这在您以编程方式在 main 方法中创建 ApplicationContext 并仅加载一个 Spring 配置文件时非常有用。

          【讨论】:

            【解决方案8】:

            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:

            ApplicationContext context = new ClassPathXMLApplicationContext("spring.xml")
            Triangle triangle =(Triangle)context.getBean("triangle");
            

            【讨论】:

              【解决方案9】:

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

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

              如果您开发一个网络应用程序,可以肯定地说您需要使用 XmlWebApplicationContext。

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

              【讨论】:

              • 这是文档中的相关部分 由于ApplicationContext 包含BeanFactory 的所有功能,因此通常建议优先使用它而不是BeanFactory,除了少数有限的情况例如在Applet 中,内存消耗可能很关键,额外的几千字节可能会有所作为。但是,对于大多数“典型”企业应用程序和系统,ApplicationContext 是您想要使用的。
              【解决方案10】:

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

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

              都是接口,

              使用实现类我们可以为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");

              【讨论】:

                【解决方案11】:

                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 接口的流行实现之一是 XMLBeanFactory,而 ApplicationContext 接口的流行实现之一是 ClassPathXmlApplicationContext.

                5. 如果您使用自动装配并使用 BeanFactory,则需要使用 API 注册 AutoWiredBeanPostProcessor,如果您使用的是 ,您可以在 XML 中配置该 API应用上下文。总之,BeanFactory 可以用于测试和非生产用途,但 ApplicationContext 是功能更丰富的容器实现,应该优于 BeanFactory

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

                【讨论】:

                • 你能否更清楚地解释你的#1,如果我在我的spring配置文件中定义了一个单例bean,那么spring容器将创建一个相同的单例,BeanFactory或ApplicationContext有什么关系在那里。
                • @pjj,当你创建 BeanFactory bf = new XmlBeanFactory(...) 的对象时,此时 BeanFactory 不会实例化任何 bean,而是当你执行 bf.getBean("myBeanRefId"); 时,容器才会构造你的特定bean 并返回对延迟加载的 bean 的引用。而对于 ApplicationContext,当您为 ApplicationContext ac = new ClassPathXmlApplicationContext(...); 创建对象时,此时容器本身会实例化配置 XML 文件中提到的所有 bean,即 Eager loading。
                【解决方案12】:

                Bean Factory 与应用程序上下文的特征矩阵sourced from spring docs

                BeanFactry和ApplicationContext的功能截图

                【讨论】:

                  【解决方案13】:

                  一个。 bean factory 和 application context 的一个区别是前者仅在调用 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 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 范围。

                  【讨论】:

                  • 点 a 和 f 相同。可以组合在一起。
                  【解决方案14】:

                  请参阅 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 之类的相当多的支持将不会生效,至少在你没有一些额外步骤的情况下不会生效。这种情况可能会令人困惑,因为配置实际上没有任何问题。

                  【讨论】:

                    【解决方案15】:

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

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

                    【讨论】:

                      【解决方案16】:

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

                      1. 仅当您调用 .getBean() 方法时,BeanFactory 才会为 spring.xml 文件 (<bean></bean>) 中提到的 bean(即 POJO 类)创建对象,但 ApplicationContext 为在加载 spring.xml 文件本身时,在 spring.xml 中配置的所有 bean(<bean></bean>,如果其范围未明确提及为“原型”)。

                      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 不是论坛,因此我编辑了您的答案,以便更直接地回答问题并避免邀请讨论。
                      【解决方案17】:

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

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

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

                      Spring bean scopes article from baeldung site

                      【讨论】:

                        【解决方案18】:

                        将 BeanFactory 用于非 Web 应用程序,因为它仅支持 Singleton 和 Prototype bean-scopes。

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

                        【讨论】:

                          【解决方案19】:

                          总结:

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

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

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

                          更多内容请看我的博文:

                          Difference between BeanFactory and ApplicationContext in Spring – The java spring blog from the basics

                          【讨论】:

                            【解决方案20】:

                            我需要解释一下 BeanFactory 和 ApplicationContext。

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

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

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

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

                            ApplicationContext 提供:

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

                            【讨论】:

                              【解决方案21】:

                              BeanFactory 表示在运行时调用getBean() 方法后惰性 实例化bean 对象的spring 容器。

                              ApplicationContext 表示 Spring 框架,它在部署期间热切在运行时不调用 getBean() 方法或在此之前实例化 bean 对象。 p>

                              【讨论】:

                                猜你喜欢
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 2014-03-26
                                • 2012-03-23
                                • 1970-01-01
                                • 1970-01-01
                                • 2015-05-31
                                相关资源
                                最近更新 更多