1. 依赖注入(Dependency Injection)和控制反转(Inversion of Control)(待补充)
"The question is, what aspect of control are [they] inverting?" Martin Fowler posed this question about Inversion of Control (IoC) on his site in 2004.
2. Spring IoC 容器的体系结构
在 Spring 中,最顶层的 IoC 容器接口是 BeanFactory。它定义了 IoC 容器的基本功能规范,但不关心你的 bean 是如何定义怎样加载的。正如我们只关心工厂里得到什么的产品对象,至于工厂是怎么生产这些对象的,这个基本的接口一点都不关心。且看它的规范:
public interface BeanFactory {
//对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,
//如果需要得到工厂本身,需要转义
String FACTORY_BEAN_PREFIX = "&";
//根据bean的名字,获取在IOC容器中得到bean实例
Object getBean(String name) throws BeansException;
//根据bean的名字和Class类型来得到bean实例,增加了类型安全验证机制。
Object getBean(String name, Class requiredType) throws BeansException;
//提供对bean的检索,看看是否在IOC容器有这个名字的bean
boolean containsBean(String name);
//根据bean名字得到bean实例,并同时判断这个bean是不是单例
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
//得到bean实例的Class类型
Class getType(String name) throws NoSuchBeanDefinitionException;
//得到bean的别名,如果根据别名检索,那么其原名也会被检索出来
String[] getAliases(String name);
}
BeanFactory 有三个子类:ListableBeanFactory、HierarchicalBeanFactory 和 AutowireCapableBeanFactory。那为何要定义这么多的子接口呢?查阅这些接口的源码和说明发现,每个接口都有他使用的场合,它们主要是为了区分在 Spring 内部在操作过程中对象的传递和转化过程中,对对象的数据访问所做的限制。例如 ListableBeanFactory 接口表示这些 Bean 是可列表的,而 HierarchicalBeanFactory 表示的是这些 Bean 是有继承关系的,也就是每个 Bean 有可能有父 Bean。AutowireCapableBeanFactory 接口定义 Bean 的自动装配规则。这四个接口共同定义了 Bean 的集合、Bean 之间的关系、以及 Bean 行为。最终 Spring 中默认提供的集结了它们所有特性的 IoC 容器是 DefaultListableBeanFactory。它的 UML 结构图如下:
如果说 BeanFactory 是个屌丝容器规范,那么 ApplicationContext 就是个高富帅容器规范。它除了能够提供 IoC 容器的基本功能外,还增加了国际化、事件的传播、资源的加载,和透明地创建上下文等附加服务。且看它的 UML 结构:
3. Spring IoC 容器的初始化过程
取 ApplicationContext 的一个标准实现 ClassPathXmlApplicationContext
作为分析案列。当执行
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(FQ_SIMPLE_CONTEXT);
跟进代码发现最终执行的构造函数里做了三件事
/**
* Create a new ClassPathXmlApplicationContext with the given parent,
* loading the definitions from the given XML files.
* @param configLocations array of resource locations
* @param refresh whether to automatically refresh the context,
* loading all bean definitions and creating all singletons.
* Alternatively, call refresh manually after further configuring the context.
* @param parent the parent context
* @throws BeansException if context creation failed
* @see #refresh()
*/
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
// 初始化基类
// 在初始化`AbstractApplicationContext`时,设置资源匹配解析器(`resourcePatternResolver`)为`PathMatchingResourcePatternResolver`
super(parent);
// 1. 设置资源的配置路径
setConfigLocations(configLocations);
// 2. 刷新容器,未启动状态即启动容器
if (refresh) {
refresh();
}
}
方法的注释写的很清楚:
- 使用给定的父对象创建新的
ClassPathXmlApplicationContext
- 从给定的 XML 文件配置里加载所有 Bean 的定义信息并为之创建单例对象
- 配置完上下文后手动刷新(启动)容器
这个方法相对比较简单,而定义在 AbstractApplicationContext
的 refresh()
方法,它是个模板方法,规范了容器启动的步骤,代码如下
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 为启动容器做准备
// Prepare this context for refreshing
prepareRefresh();
// 2. 告诉子类去刷新内部的bean工厂
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 准备bean工厂在上下文的使用
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// 4. 允许bean工厂在上下文中的子类进行后处理
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// 5. 调用以bean形式注册在上下文里的工厂处理器
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册拦截bean创建的bean处理器
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// 7. 初始化上下文的消息资源(国际化)
// Initialize message source for this context.
initMessageSource();
// 8. 初始化上下文的事件广播器
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// 9. 初始化上下文里指定子类其他指定的bean
// Initialize other special beans in specific context subclasses.
onRefresh();
// 10. 检查事件监听器并注册
// Check for listener beans and register them.
registerListeners();
// 11. 初始化剩余的(非延迟加载)单例Beans
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// 12. 发布一致的事件
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 1. 销毁已经创建的单例避免资源的挂起
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// 2. 重置“激活”状态
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// 当我们可能不再为单例Beans需要元数据时,重置在Spring Core模块中通用内省的缓存
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于