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(); } } }
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于