题目
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 的方案可供选择,我们先来看看大体的继承结构是怎么样的:

除了 ClassPathXmlApplicationContext,我们也可以使用绿颜色的 `FileSystemXmlApplicationContext` 和 `AnnotationConfigApplicationContext` 这两个类:
- `FileSystemXmlApplicationContext` 的构造函数需要一个 xml 配置文件在系统中的路径,其他和 ClassPathXmlApplicationContext 基本上一样
- `AnnotationConfigApplicationContext` 是基于注解来使用的,它不需要配置文件,采用 Java 配置类和各种注解来配置,是比较简单的方式,也是大势所趋吧。
**`ApplicationContext` 启动过程中,会负责创建实例 Bean,往各个 Bean 中注入依赖等**。
所以,**要弄懂 IoC,其实就是弄清楚该怎么样通过配置文件来启动 Spring 的 `ApplicationContext`**
## BeanFactory 和 ApplicationContext 的区别
`BeanFactory`,从名字上也很好理解,**生产 bean 的工厂,它负责生产和管理各个 bean 实例**。
**`ApplicationContext` 其实就是一个 BeanFactory(`ApplicationContext` 继承自 BeanFactory)**。
和 BeanFactory 接口相关的主要的继承结构:

- 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
>
> 
>
> 另外,所有的 beanNames,也用 ArrayList 存起来了即 `beanDefinitionNames`
对于二者的用途,我们可以进行简单的划分:
- BeanFactory 接口定义了 `getBean()`、`containsBean()`等管理 Bean 的通用方法,Spring 给出了 BeanFacotry 的很多种实现,如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext 等,都是在 BeanFactory 的基础上附加了其他功能,也就是说,**BeanFactory 的功能通过其他接口得到不断扩展**
- ApplicationContext 继承自 BeanFactory ,包含 BeanFactory 的所有功能,面向使用 Spring 框架的开发者,几乎所有的应用场合都可以直接使用 ApplicationContext 而非底层的 BeanFactory
