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

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

我明白那个 ApplicationContext 延伸 BeanFactory, ,但是如果我只是编写一个简单的 main 方法,我是否需要额外的功能 ApplicationContext 提供?到底是什么样的额外功能 ApplicationContext 提供?

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

这个答案在网络环境中是否会改变——如果我的任何类需要了解 Spring,他们是否更有可能需要 ApplicationContext?

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

有帮助吗?

解决方案

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

豆工厂

  • Bean实例化/连接

应用上下文

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

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

其他提示

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

  

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

鉴于此,我最初选择ClassPathXmlApplicationContext用于集成/性能测试,因为我不想加载整个应用程序来测试隔离的bean。但是 - 如果我错了,有人会纠正我 - <=>不支持<=> XML配置。所以<=>和<=>每个都提供了我想要的关键功能,但两者都没有。

我可以说,关于覆盖默认实例化行为的文档中的注释发生在配置中,并且它是每个bean,所以我不能只设置<!> quot; lazy-init <!> QUOT; XML文件中的属性,或者我坚持维护它的一个版本用于测试,一个用于部署。

我最终做的是将<=>扩展到懒惰加载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提供了两种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                            |
+---------------------------------------+-----------------+--------------------------------+

enter image description here

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

例子:

  ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeansConfiguration.class);
  • ApplicationContext 是由 a 初始化的容器 ContextLoaderListener 或者 ContextLoaderServlet 定义在一个 web.xmlContextLoaderPlugin 定义于 struts-config.xml.

笔记: XmlBeanFactory已弃用 从 Spring 3.1 开始支持 DefaultListableBeanFactoryXmlBeanDefinitionReader.

要添加Miguel Ping的回答,这里是文档中的另一部分也回答了这个问题:

  

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

(为未来可能会阅读此问题的春季新手发布此内容)

  1. ApplicationContext 是比 BeanFactory

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

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

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

即使您没有使用ApplicationContext提供的所有内容,最好还是使用它,然后如果您决定使用某些资源(如消息或后处理器)或其他模式来添加事务性建议,这样,您将拥有一个ApplicationContext,不需要更改任何代码。

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

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

<强>的ApplicationContext: 它加载在spring配置文件中配置的spring bean,并管理spring bean的生命周期和WHEN CONTAINER STARTS.It不会等到 getBean(<!> quot; springbeanref <!> quot;)被称为。

<强>的BeanFactory  它加载在spring配置文件中配置的spring bean,当我们调用 getBean(<!> quot; springbeanref <!> quot;)时管理spring bean的生命周期。当我们调用<时在spring bean生命周期开始时strong> getBean(<!> quot; springbeanref <!> quot;)

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

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

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

如果你想让你的bean知道Spring,你可以让它们为它实现BeanFactoryAware和/或ApplicationContextAware,这样你就可以使用BeanFactory或ApplicationContext并选择要实现的接口。

Bean工厂应用上下文 两者都是从春天获取豆子的方法 国际奥委会 容器,但还是有一些区别。

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

Bean工厂应用上下文 两者都是 Java 接口,并且 ApplicationContext 扩展了 BeanFactory。两者都是使用XML配置文件进行配置。简而言之 BeanFactory 提供了基本的控制反转(国际奥委会)和依赖注入(DI) 特性而 ApplicationContext 提供 先进的 特征。

BeanFactory 由接口“org.springframework.beans.factory" 其中 BeanFactory,其有多种实现。

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

不同之处

  1. Bean工厂 当你调用时实例化bean 获取Bean() 方法,而ApplicationContext在容器启动时实例化Singleton bean,它不会等待getBean()被调用。

  2. Bean工厂 不提供国际化支持,但 应用上下文 为其提供支持。

  3. 之间的另一个区别 Bean工厂应用上下文 能够将事件发布到注册为侦听器的 bean。

  4. 流行的实现之一 Bean工厂 接口是 XMLBeanFactory 而流行的实现之一 应用上下文 接口是 类路径XmlApplicationContext.

  5. 如果您使用自动接线并使用 Bean工厂 比您需要注册的 自动连线Bean后处理器 使用 API,如果您正在使用,则可以在 XML 中配置该 API 应用上下文. 。总之 Bean工厂 对于测试和非生产用途来说是可以的,但是 应用上下文 是功能更丰富的容器实现,应该受到青睐 Bean工厂

  6. Bean工厂 默认情况下支持 懒惰的 加载和 应用上下文 默认支持 攻击性 加载中。

BeanFactory ApplicationContext 的区别如下:

  1. BeanFactory使用延迟初始化,但 ApplicationContext使用急切初始化。对于BeanFactory,在调用getBeans()方法时会创建bean,但是在创建ApplicationContext对象时,在ApplicationContext的情况下会创建bean。
  2. BeanFactory使用语法显式提供资源对象,但 ApplicationContext自己创建和管理资源对象。
  3. BeanFactory不支持国际化,但 ApplicationContext支持国际化。
  4. 不支持基于BeanFactory注释的依赖注入但ApplicationContext支持基于注释的依赖注入。
  5. 使用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");

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

BeanFacotry和ApplicationContext

的功能截图

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

  1. 使用BeatFactory
  2. 使用ApplicationContext
  3. 两者都是接口

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

    解决差异

    BeanFactory

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

    2. 不支持I18N

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

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

    5. ex:BeanFactory context = new XmlBeanFactory(new Resource(<!> quot; applicationContext.xml <!> quot;));

      的ApplicationContext

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

      2. 支持I18N

      3. 默认支持Aggresive loading。

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

      5. 例如:结果 ApplicationContext context = new ClasspathXmlApplicationContext(<!> quot; applicationContext.xml <!> quot;);

一个。 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类的服务类的配置细节。这里ClassPathXmlApplicationContext是ApplicationContext的子代。

℃。 BeanFactory Container是基本容器,它只能创建对象并注入依赖项。但我们可以<!>#8217;附加其他服务,如安全性,事务,消息传递等,以提供我们使用ApplicationContext Container的所有服务。

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

即BeanFactory Container不支持AutoScanning(基于支持注释的依赖注入)的功能,但ApplicationContext Container支持。

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

克。 Beanfactory Container仅支持bean的两个范围(singleton <!> amp; prototype)。但ApplicationContext Container支持所有bean范围。

ApplicationContext是BeanFactory的一个大兄弟,这将是BeanFactory提供的所有功能以及许多其他功能。

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

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

  1. 仅当您调用.getBean()方法时,BeanFactory才会为spring.xml文件(<bean></bean>)中提到的bean(即POJO类)创建对象,但ApplicationContext会为其创建对象所有bean(<=>,如果其范围未明确提及为<!> quot; Prototype <!>;;)在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的对象,因此是Eager容器)

    ApplicationContext context = new ClassPathXmlApplicationContext("com/ioc/constructorDI/resources/spring.xml");
    
  3. 从技术上讲,建议使用ApplicationContext,因为在实时应用程序中,将在服务器本身启动应用程序时创建bean对象。这减少了用户请求的响应时间,因为对象已经可以响应。

我认为值得一提的是,从Spring 3开始,如果你想创建一个工厂,你也可以使用 @configuration 注释结合正确的 @scope

@Configuration
public class MyFactory {

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

Spring容器应使用 @ComponentScan 注释或xml配置

来自baeldung网站的Spring bean范围文章

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

虽然ApplicationContext容器支持所有bean范围,因此您应该将它用于Web应用程序。

总结:

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

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

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

有关详情,请参阅我的博文:

Spring中的BeanFactory和ApplicationContext之间的区别<!>#8211 ;来自基础知识的java spring博客

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top