IOC 是如何工作的?
通过 ApplicationContext 创建 Spring 容器,容器读取配置文件 “/beans.xml” 并管理定义的 Bean 实例对象。
通过 ApplicationContext.getBean 获取 Bean 实例。
IOC 容器经历的几个阶段:Resource 定位、载入 BeanDefinition、将 BeanDefinition 注册到容器。
Resource 定位
Resource 是 Spring 中用于封装 I/O 操作的接口。主要有:
FileSystemResource:以文件绝对路径进行资源访问
ClassPathResource:以类路径的方式访问资源
ServletContextResource:web 应用根目录的方式访问资源
UrlResource:访问网络资源的实现类
ByteArrayResource:访问字节数组资源的实现类
Spring 提供了 ResourceLoader 接口用于实现不同的 Resource 加载策略,该接口的实例对象可以获取一个 Resource 对象。
在 ResourceLoader 接口中定义了两个方法:
Resource getResource(String location); // 通过提供的资源 location 参数获取 Resource 实例
ClassLoader getClassLoader(); // 获取 ClassLoader, 通过 ClassLoader 可将资源载入 JVM
ApplicationContext 的所有实现类都实现了 ResourceLoader 接口,所以可以直接调用 getResource 获取 Resource 对象。
获取到 Resource 后就完成了资源定位,接下来就可以用 I/O 载入 Bean.
载入 BeanDefinition
BeanDefinition 是一个数据结构(interface),描述了一个 bean 实例,它具有属性值、构造函数参数值以及由具体实现提供的更多信息。
Bean 会在 Spring IOC 容器内以 BeanDefinition 的形式存在,IOC 容器对 Bean 的管理和依赖注入都是通过操作 BeanDefinition 来完成的。
Resource 定位后,由 ApplicationContext 的实现类读取 Resource,并加载为 BeanDefinition。
我们通常使用 @Configuration 配置类来定义 Bean,这类 Bean 就是通过 AnnotationConfigApplicationContext 获取的。
obtainFreshBeanFactory()
在之前的文章中说到,Spring 上下文初始化最重要的方法 refresh(),其中有4个方法,
而 obtainFreshBeanFactory() 就是用于解析 Spring 配置文件,
将所有 Spring 配置文件中的 Bean 定义封装成 BeanDefinition,加载到 BeanFactory 中。
以下是 IOC 容器初始化流程图