BeanFactory和ApplicationContext区别及详解

这篇具有很好参考价值的文章主要介绍了BeanFactory和ApplicationContext区别及详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.概述

​ Spring 框架带有两个 IOC 容器—— BeanFactoryApplicationContextBeanFactory是 IOC 容器的最基本版本,ApplicationContext扩展了BeanFactory的特性。

​ Spring容器最基本的接口就是BeanFactory。BeanFactory负责配置、创建、管理Bean,它有一个子接口ApplicationContext,也被称为Spring上下文,容器同时还管理着Bean和Bean之间的依赖关系。

​ spring Ioc容器的实现,从根源上是beanfactory,但真正可以作为一个可以独立使用的ioc容器还是DefaultListableBeanFactory,因此可以这么说,DefaultListableBeanFactory 是整个spring ioc的始祖。

1.1BeanFactory

BeanFactory和ApplicationContext区别及详解

接口介绍

1.BeanFactory接口:
 是Spring bean容器的根接口,提供获取bean,是否包含bean,是否单例与原型,获取bean类型,bean 别名的方法 。它最主要的方法就是getBean(String beanName)。
2.BeanFactory的三个子接口:

  • HierarchicalBeanFactory:提供父容器的访问功能
  • ListableBeanFactory:提供了批量获取Bean的方法
  • AutowireCapableBeanFactory:在BeanFactory基础上实现对已存在实例的管理
    3.ConfigurableBeanFactory:
    主要单例bean的注册,生成实例,以及统计单例bean
    4.ConfigurableListableBeanFactory:
    继承了上述的所有接口,增加了其他功能:比如类加载器,类型转化,属性编辑器,BeanPostProcessor,作用域,bean定义,处理bean依赖关系, bean如何销毁…
    5.实现类DefaultListableBeanFactory详细介绍:
    实现了ConfigurableListableBeanFactory,实现上述BeanFactory所有功能。它还可以注册BeanDefinition
    接口详细介绍请参考:揭秘BeanFactory

接口具体说明

1、BeanFactory作为一个主接口不继承任何接口,暂且称为一级接口
  2、有3个子接口继承了它,进行功能上的增强。这3个子接口称为二级接口
  3、ConfigurableBeanFactory可以被称为三级接口,对二级接口HierarchicalBeanFactory进行了再次增强,它还继承了另一个外来的接口SingletonBeanRegistry
  4、ConfigurableListableBeanFactory是一个更强大的接口,继承了上述的所有接口,无所不包,称为四级接口。(这4级接口是BeanFactory的基本接口体系。继续,下面是继承关系的2个抽象类和2个实现类)
  5、AbstractBeanFactory作为一个抽象类,实现了三级接口ConfigurableBeanFactory大部分功能。
  6、AbstractAutowireCapableBeanFactory同样是抽象类,继承自AbstractBeanFactory,并额外实现了二级接口AutowireCapableBeanFactory
  7、DefaultListableBeanFactory继承自AbstractAutowireCapableBeanFactory,实现了最强大的四级接口ConfigurableListableBeanFactory,并实现了一个外来接口BeanDefinitionRegistry,它并非抽象类。
  8、最后是最强大的XmlBeanFactory,继承自DefaultListableBeanFactory,重写了一些功能,使自己更强大。

1、BeanFactory作为一个主接口不继承任何接口,暂且称为一级接口
  2、有3个子接口继承了它,进行功能上的增强。这3个子接口称为二级接口
  3、ConfigurableBeanFactory可以被称为三级接口,对二级接口HierarchicalBeanFactory进行了再次增强,它还继承了另一个外来的接口SingletonBeanRegistry
  4、ConfigurableListableBeanFactory是一个更强大的接口,继承了上述的所有接口,无所不包,称为四级接口
  (这4级接口是BeanFactory的基本接口体系。继续,下面是继承关系的2个抽象类和2个实现类:)
  5、AbstractBeanFactory作为一个抽象类,实现了三级接口ConfigurableBeanFactory大部分功能。
  6、AbstractAutowireCapableBeanFactory同样是抽象类,继承自AbstractBeanFactory,并额外实现了二级接口AutowireCapableBeanFactory
  7、DefaultListableBeanFactory继承自AbstractAutowireCapableBeanFactory,实现了最强大的四级接口ConfigurableListableBeanFactory,并实现了一个外来接口BeanDefinitionRegistry,它并非抽象类。
  8、最后是最强大的XmlBeanFactory,继承自DefaultListableBeanFactory,重写了一些功能,使自己更强大。

源码说明

public interface BeanFactory {

    /**
     * 用来引用一个实例,或把它和工厂产生的Bean区分开,就是说,如果一个FactoryBean的名字为a,那么,&a会得到那个Factory
     */
    String FACTORY_BEAN_PREFIX = "&";
    /*
     * 四个不同形式的getBean方法,获取实例
     */
    Object getBean(String name) throws BeansException;

    <T> T getBean(String name, Class<T> requiredType) throws BeansException;

    <T> T getBean(Class<T> requiredType) throws BeansException;

    Object getBean(String name, Object... args) throws BeansException;
 	// 根据名称判断bean是否存在
    boolean containsBean(String name);
	// 是否为单实例Bean
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
	// 是否为原型(多实例)
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
	// 名称、类型是否匹配
    boolean isTypeMatch(String name, Class<?> targetType)
            throws NoSuchBeanDefinitionException;
	// 获取类型
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;
	// 根据实例的名字获取实例的别名
    String[] getAliases(String name);
}

2.延迟加载与立即加载

BeanFactory按需加载 bean,而ApplicationContext在启动时加载所有 bean

因此, BeanFactory与 ApplicationContext相比是轻量级的。例子如下:

2.1.使用BeanFactory延迟加载

假设我们有一个名为Student的单例 bean类,它有一个方法:

public class Student {
    public static boolean isBeanInstantiated = false;
    public void postConstruct() {
        setBeanInstantiated(true);
    }
    //standard setters and getters
}

我们将 在BeanFactory配置文件ioc-container-difference-example.xml中将*postConstruct()*方法定义为init-method

<bean id="student" class="com.baeldung.ioccontainer.bean.Student" 
      init-method="postConstruct"/>

现在,让我们编写一个测试用例,创建一个BeanFactory来检查它是否加载了Student bean:

@Test
public void whenBFInitialized_thenStudentNotInitialized() {
    Resource res = new ClassPathResource("ioc-container-difference-example.xml");
    BeanFactory factory = new XmlBeanFactory(res);
    
    assertFalse(Student.isBeanInstantiated());
}

在这里,Student对象没有被初始化。换句话说,只有BeanFactory被初始化只有当我们显式调用getBean()方法时,我们的BeanFactory中定义的 bean才会被加载*。*

让我们检查一下我们手动调用getBean()方法的Student bean的初始化:

@Test
public void whenBFInitialized_thenStudentInitialized() {
    Resource res = new ClassPathResource("ioc-container-difference-example.xml");
    BeanFactory factory = new XmlBeanFactory(res);
    Student student = (Student) factory.getBean("student");

    assertTrue(Student.isBeanInstantiated());
}

在这里,Student bean 加载成功。因此,BeanFactory仅在需要时才加载 bean。

2.2. 使用ApplicationContext预加载

现在,让我们使用ApplicationContext代替BeanFactory

我们将只定义*ApplicationContext,*它会通过使用立即加载策略立即加载所有 bean:

@Test
public void whenAppContInitialized_thenStudentInitialized() {
    ApplicationContext context = new ClassPathXmlApplicationContext("ioc-container-difference-example.xml");
    
    assertTrue(Student.isBeanInstantiated());
}

在这里,即使我们没有调用getBean()方法,也会创建Student对象。

ApplicationContext被认为是一个沉重的 IOC 容器,因为它的预先加载策略会在启动时加载所有 bean。相比之下, BeanFactory是轻量级的,可以在内存受限的系统中使用。尽管如此,我们最常用的仍是ApplicationContext

3.ApplicationContext

ApplicationContext以更加面向框架的风格增强了BeanFactory,并提供了一些适用于企业应用程序的特性。

  • 默认初始化所有的Singleton,也可以通过配置取消预初始化。

  • 继承MessageSource,因此支持国际化。

  • 资源访问,比如访问URL和文件。

  • 事件传播特性,即支持aop特性。

  • 同时加载多个配置文件。

  • 以声明式方式启动并创建Spring容器。

ApplicationContext:是IOC容器另一个重要接口, 它继承了BeanFactory的基本功能, 同时也继承了容器的高级功能,如:MessageSource(国际化资源接口)、ResourceLoader(资源加载接口)、ApplicationEventPublisher(应用事件发布接口)等。

4. BeanFactoryPostProcessor和BeanPostProcessor的自动注册

ApplicationContext在启动时会**自动注册BeanFactoryPostProcessor和****BeanPostProcessor 。**另一方面,BeanFactory不会自动注册这些接口。

4.1.在BeanFactory中注册

为了理解,让我们编写两个类。

首先,我们有CustomBeanFactoryPostProcessor类,它实现了BeanFactoryPostProcessor

public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    private static boolean isBeanFactoryPostProcessorRegistered = false;
    
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory){
        setBeanFactoryPostProcessorRegistered(true);
    }

    // standard setters and getters
}

在这里,我们重写了postProcessBeanFactory() 方法来检查它的注册。

其次,我们有另一个类CustomBeanPostProcessor,它实现了BeanPostProcessor

public class CustomBeanPostProcessor implements BeanPostProcessor {
    private static boolean isBeanPostProcessorRegistered = false;
    
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName){
        setBeanPostProcessorRegistered(true);
        return bean;
    }

    //standard setters and getters
}

在这里,我们重写了postProcessBeforeInitialization()方法来检查它的注册。

此外,我们在ioc-container-difference-example.xml配置文件中配置了这两个类:

<bean id="customBeanPostProcessor" 
  class="com.baeldung.ioccontainer.bean.CustomBeanPostProcessor" />
<bean id="customBeanFactoryPostProcessor" 
  class="com.baeldung.ioccontainer.bean.CustomBeanFactoryPostProcessor" />

让我们看一个测试用例来检查这两个类是否在启动时自动注册:

@Test
public void whenBFInitialized_thenBFPProcessorAndBPProcessorNotRegAutomatically() {
    Resource res = new ClassPathResource("ioc-container-difference-example.xml");
    ConfigurableListableBeanFactory factory = new XmlBeanFactory(res);

    assertFalse(CustomBeanFactoryPostProcessor.isBeanFactoryPostProcessorRegistered());
    assertFalse(CustomBeanPostProcessor.isBeanPostProcessorRegistered());
}

从我们的测试中可以看出,自动注册没有发生

现在,让我们看一个在BeanFactory中手动添加它们的测试用例:

@Test
public void whenBFPostProcessorAndBPProcessorRegisteredManually_thenReturnTrue() {
    Resource res = new ClassPathResource("ioc-container-difference-example.xml");
    ConfigurableListableBeanFactory factory = new XmlBeanFactory(res);

    CustomBeanFactoryPostProcessor beanFactoryPostProcessor 
      = new CustomBeanFactoryPostProcessor();
    beanFactoryPostProcessor.postProcessBeanFactory(factory);
    assertTrue(CustomBeanFactoryPostProcessor.isBeanFactoryPostProcessorRegistered());

    CustomBeanPostProcessor beanPostProcessor = new CustomBeanPostProcessor();
    factory.addBeanPostProcessor(beanPostProcessor);
    Student student = (Student) factory.getBean("student");
    assertTrue(CustomBeanPostProcessor.isBeanPostProcessorRegistered());
}

在这里,我们使用postProcessBeanFactory()方法注册CustomBeanFactoryPostProcessoraddBeanPostProcessor()方法注册CustomBeanPostProcessor。在这种情况下,他们俩都成功注册。

4.2. 在ApplicationContext中注册

正如我们前面提到的,ApplicationContext会自动注册这两个类,而无需编写额外的代码。

让我们在单元测试中验证此行为:

@Test
public void whenAppContInitialized_thenBFPostProcessorAndBPostProcessorRegisteredAutomatically() {
    ApplicationContext context 
      = new ClassPathXmlApplicationContext("ioc-container-difference-example.xml");

    assertTrue(CustomBeanFactoryPostProcessor.isBeanFactoryPostProcessorRegistered());
    assertTrue(CustomBeanPostProcessor.isBeanPostProcessorRegistered());
}

如我们所见,在这种情况下**,两个类的自动注册都是成功的。**

因此,始终建议使用ApplicationContext,因为 Spring 2.0(及更高版本)大量使用BeanPostProcessor。

还值得注意的是,如果您使用的是普通的BeanFactory,那么事务和 AOP 等功能将不会生效(至少在不编写额外代码行的情况下不会生效)。这可能会导致混淆,因为配置看起来没有任何问题。

5. 结论

  1. BeanFactory负责读取bean配置文档,管理bean的加载,实例化,维护bean之间的依赖关系,负责bean的声明周期。

  2. ApplicationContext除了提供上述BeanFactory所能提供的功能之外,还提供了更完整的框架功能:
    a. 国际化支持
    b. 资源访问:Resource rs = ctx. getResource(“classpath:config.properties”), “file:c:/config.properties”
    c. 事件传递:通过实现ApplicationContextAware接口。

  3. 常用的获取ApplicationContext

FileSystemXmlApplicationContext:从文件系统或者url指定的xml配置文件创建,参数为配置文件名或文件名数组,有相对路径与绝对路径。

ApplicationContext factory=new FileSystemXmlApplicationContext("src/applicationContext.xml");
ApplicationContext factory=new FileSystemXmlApplicationContext("E:/Workspaces/MyEclipse 8.5/Hello/src/applicationContext.xml");

ClassPathXmlApplicationContext:从classpath的xml配置文件创建,可以从jar包中读取配置文件。ClassPathXmlApplicationContext 编译路径总有三种方式:

ApplicationContext factory = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
ApplicationContext factory = new ClassPathXmlApplicationContext("applicationContext.xml"); 
ApplicationContext factory = new ClassPathXmlApplicationContext("file:E:/Workspaces/MyEclipse 8.5/Hello/src/applicationContext.xml");

XmlWebApplicationContext:从web应用的根目录读取配置文件,需要先在web.xml中配置,可以配置监听器或者servlet来实现

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
<servlet-name>context</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

这两种方式都默认配置文件为web-inf/applicationContext.xml,也可使用context-param指定配置文件文章来源地址https://www.toymoban.com/news/detail-409671.html

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/myApplicationContext.xml</param-value>
</context-param>

到了这里,关于BeanFactory和ApplicationContext区别及详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 进阶Spring(2)-BeanFactory和ApplicationContext实现

    🏠个人主页:阿杰的博客 💪个人简介:大家好,我是阿杰,一个正在努力让自己变得更好的男人👨 目前状况🎉:24届毕业生,奋斗在找实习的路上🌟 🚗🚗为了让更多的人看到更优质的博客,阿杰正在努力的更新学习中心中的内容。 首先看代码 spring底层创建实体类就是

    2024年02月05日
    浏览(39)
  • Mr. Cappuccino的第60杯咖啡——Spring之BeanFactory和ApplicationContext

    概述 BeanFactory,以Factory结尾,表示它是一个工厂类(接口), 它是负责生产和管理bean的一个工厂。在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖; BeanFactory只是个接口,并不是IOC容器的具体实现,但是

    2024年02月13日
    浏览(41)
  • 理解SpringIOC和DI第一课(Spring的特点),IOC对应五大注解,ApplicationContext vs BeanFactory

    对象这个词在Spring范围内,称为bean Spring两大核心思想 1.IOC     (IOC是控制反转,意思是 控制权反转-控制权(正常是谁用这个对象,谁去创建,)-控制对象的控制权,反转的意思是创建对象的控制权,交给了Spring) 优点:解耦合 高内聚:一个模块内部的关系 低耦合:各个模

    2024年02月04日
    浏览(45)
  • BeanFactory与ApplicationContext基本介绍

    接口 定义能力, 抽象类 实现接口的一些重要方法,最后 实现类 可以实现自己的一些逻辑 仅仅是一个接口,Spring 的核心容器,并不是IOC容器的具体实现,它的一些具体实现类才是 BeanFactory 是 ApplicationContext 的父接口 BeanFactory才是 Spring 的核心容器, 主要的 ApplicationContext 实现

    2024年02月13日
    浏览(37)
  • 第一讲:BeanFactory和ApplicationContext接口

    BeanFactory是ApplicationContext的父接口,是真正的Spring核心容器,主要的ApplicationContext实现都【组合】了他的功能。 首先先看一下BeanFactory的接口定义: 表面上只有getBean功能,实际上控制反转、基本的依赖注入、直至Bean的生命周期的各种功能,都由他的实现类提供, 例如:Defau

    2024年02月12日
    浏览(35)
  • 解锁ApplicationContext vs BeanFactory: 谁更具选择性?

    目录 一、聚焦源码回顾 (一)源码分析和理解 (二)简短的回顾对比建议 二、ApplicationContext vs BeanFactory特性对比 (一)主要特性总结 (二)直接建议 三、案例简单说明 (一)加载少量的 Bean的案例 (二)简单的命令行工具:用于读取配置文件并生成报告 (三)启动时加

    2024年04月25日
    浏览(32)
  • Spring源码系列(补充):详解ApplicationContext

    在之前的文章中,我们已经对Spring源码中的一些核心概念进行了分析。由于篇幅限制,我们并没有详细解释ApplicationContext类所继承的父接口及其作用。因此,本文将单独为ApplicationContext进行详细说明,包括其继承的父接口及其作用。 大家应该都比较熟悉MessageSource,它用于国

    2023年04月21日
    浏览(40)
  • Spring MVC学习随笔-控制器(Controller)开发详解:调用业务对象、父子工厂拆分(applicationContext.xml、dispatcher.xml)

    学习视频:孙哥说SpringMVC:结合Thymeleaf,重塑你的MVC世界!|前所未有的Web开发探索之旅 💡 1. 接收客户端(Client)请求参数【讲解完毕】2. 调用业务对象【讲解】3. 页面跳转 dispatcher.xml DAO Service Controller 现有SSM开发中存在的问题 MVC层的对象(Controller, mvc:annotation-driven/,视图解

    2024年02月05日
    浏览(49)
  • Spring源码-浅识BeanFactory

    在SpringBoot出现之前,我们使用Spring需要以配置文件的方式进行启动.如果使用XML文件配置.则通过 XmlWebApplicationContext.java 进行启动.常应用在Web项目的开发中. 以此为例,通过阅读源码发现和 XmlWebApplicationContext.java \\\"平级\\\"的类如下所示 由此我们可以知道 ApplicationContext 遵循 Applicat

    2024年02月03日
    浏览(43)
  • 深度解析 Spring 源码:揭秘BeanFactory 之谜

    1.1 BeanFactory的概述 BeanFactory是Spring框架中的一个核心接口,它提供了一种灵活的方式来管理Bean,并实现了IoC(控制反转)和DI(依赖注入)等特性,为应用程序提供了灵活、可扩展的对象管理和配置机制。 BeanFactory的特性 : IoC容器: BeanFactory是Spring的IoC容器之一。IoC是一种

    2024年04月26日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包