题目
BeanFactory 和 ApplicationContext 有什么作用?两者之间的区别是什么
答案
@[toc] --- ## 什么是 BeanFactory 和 ApplicationContext 来看一个最基础的 IoC 用法: 首先,定义一个接口: ```java public interfaceMessageService { StringgetMessage(); } ``` 定义接口实现类: ```java public classMessageServiceImpl implementsMessageService { public StringgetMessage() { return "hello world"; } } ``` 接下来,我们在 **resources** 目录新建一个配置文件,文件名随意,通常叫 application.xml 或 application-xxx.xml 就可以了: ```xml <beans> <bean id="messageService" class="com.javadoop.example.MessageServiceImpl"/> </beans> ``` 这样,我们就可以跑起来了: ```java public classApp { public static voidmain(String[] args) { // 用配置文件来启动一个 ApplicationContext ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml"); System.out.println("context 启动成功"); // 从 ApplicationContext 中取出 Bean,而不是用 new MessageServiceImpl() 这种方式 MessageService messageService = context.getBean(MessageService.class); // 输出: hello world System.out.println(messageService.getMessage()); } } ``` `ApplicationContext context = new ClassPathXmlApplicationContext(...)` 其实很好理解,从名字上就可以猜出一二,就是**在 ClassPath 中寻找 xml 配置文件,根据 xml 文件内容来构建 `ApplicationContext`**。当然,除了 `ClassPathXmlApplicationContext` 以外,我们也还有其他构建 ApplicationContext 的方案可供选择,我们先来看看大体的继承结构是怎么样的: ![](https://cs-wiki.oss-cn-shanghai.aliyuncs.com/img/image-20220709205220158.png) 除了 ClassPathXmlApplicationContext,我们也可以使用绿颜色的 `FileSystemXmlApplicationContext` 和 `AnnotationConfigApplicationContext` 这两个类: - `FileSystemXmlApplicationContext` 的构造函数需要一个 xml 配置文件在系统中的路径,其他和 ClassPathXmlApplicationContext 基本上一样 - `AnnotationConfigApplicationContext` 是基于注解来使用的,它不需要配置文件,采用 Java 配置类和各种注解来配置,是比较简单的方式,也是大势所趋吧。 **`ApplicationContext` 启动过程中,会负责创建实例 Bean,往各个 Bean 中注入依赖等**。 所以,**要弄懂 IoC,其实就是弄清楚该怎么样通过配置文件来启动 Spring 的 `ApplicationContext`** ## BeanFactory 和 ApplicationContext 的区别 `BeanFactory`,从名字上也很好理解,**生产 bean 的工厂,它负责生产和管理各个 bean 实例**。 **`ApplicationContext` 其实就是一个 BeanFactory(`ApplicationContext` 继承自 BeanFactory)**。 和 BeanFactory 接口相关的主要的继承结构: ![](https://cs-wiki.oss-cn-shanghai.aliyuncs.com/img/image-20220709205510887.png) - BeanFactory 接口位于类结构树的顶端,它定义了 `getBean()`、`containsBean()`等管理 Bean 的通用方法,Spring 给出了很多种实现,如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext 等,都是在 BeanFactory 的基础上附加了其他功能,也就是说,**BeanFactory 的功能通过其他接口得到不断扩展** - ApplicationContext 继承了 `ListableBeanFactory`,**这个 Listable 的意思就是,通过这个接口,我们可以获取多个 Bean,大家看源码会发现,最顶层 BeanFactory 接口的方法都是获取单个 Bean 的**。 如果说 `BeanFactory` 是 Spring 的 “心脏”,那么 `ApplicationContext` 就是完整的“身躯”了。ApplicationContext 由 BeanFactory 派生而来,提供了更多面向实际应用的功能。**在 BeanFactory 中,很多功能需要以编程的方式实现,而在 ApplicationContext 中则可以通过配置的方式实现**。 **我们一般称 BeanFactory 为 IoC 容器,而称 ApplicationContext 为应用上下文**。但有时为了行文方便,我们也将 ApplicationContext 称为 Spring 容器。 > **Spring 会根据 Bean 的配置或者配置文件生成一个一个的【`BeanDefinition`】,然后存到 BeanFactory 中,具体来说,是存在 `DefaultListableBeanFactory.beanDefinitionMap` 这个 Map 里面**(这个步骤也称为 “加载 Bean”,对应 `loadBeanDefinitions(beanFactory)` 方法),这也就是为啥我们说 IoC 容器其实就是个 Map > > ![](https://cs-wiki.oss-cn-shanghai.aliyuncs.com/img/image-20220709210308535.png) > > 另外,所有的 beanNames,也用 ArrayList 存起来了即 `beanDefinitionNames` 对于二者的用途,我们可以进行简单的划分: - BeanFactory 接口定义了 `getBean()`、`containsBean()`等管理 Bean 的通用方法,Spring 给出了 BeanFacotry 的很多种实现,如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext 等,都是在 BeanFactory 的基础上附加了其他功能,也就是说,**BeanFactory 的功能通过其他接口得到不断扩展** - ApplicationContext 继承自 BeanFactory ,包含 BeanFactory 的所有功能,面向使用 Spring 框架的开发者,几乎所有的应用场合都可以直接使用 ApplicationContext 而非底层的 BeanFactory