引言
spring容器就像一台构造精妙的机器,我们通过配置文件向机器传达控制信息,机器就能够按照设定的模式工作。如果将spring容器比作一辆车,那么可以将beanfactory看成汽车的发动机,而ApplicationContext则是一辆完整的汽车,它不但包括发动机,还包括离合器、变速器及底盘、车身、电气设备等其他组件。在ApplicationContext内,各个组件按部就班、有条不絮地完成汽车的各项功能。
内部工作机制
Spring的AbstractApplicationContext是ApplicationContext的抽象实现类,该抽象类的refresh()方法定义了spring容器在加载配置文件后的各项处理过程,这些处理过程清新地刻画了spring容器启动时所执行地各项操作:
@Override
public void refresh() throws BeansException,IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListablebeanfactory beanfactory = obtainFreshbeanfactory();
// Prepare the bean factory for use in this context.
preparebeanfactory(beanfactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessbeanfactory(beanfactory);
// Invoke factory processors registered as beans in the context.
invokebeanfactoryPostProcessors(beanfactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanfactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishbeanfactoryInitialization(beanfactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core,since we
// might not ever need Metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
- 初始化beanfactory:根据配置文件实例化beanfactory,在obtainFreshbeanfactory()方法中,首先调用refreshbeanfactory()方法刷新beanfactory,然后调用getbeanfactory()方法获取beanfactory,这两个方法都是由具体子类实现。在这一步里,Spring将配置文件的信息装入容器的Bean定义注册表(BeanDeFinitionRegistry)中,但是此时Bean还没有初始化;
- 调用工厂后处理器:根据反射机制从BeanDeFinitionRegistry中找出所有实现了beanfactoryPostProcessor接口的Bean,并调用其postProcessbeanfactory()接口方法;
- 注册Bean后处理器:根据反射机制从BeanDefintionRegistry中找出所有实现了BeanPostProcessor接口的Bean,并将它们注册到容器Bean后处理的注册表;
- 初始化消息源:初始化容器的国际化消息资源;
- 初始化应用上下文事件广播器;
- 初始化其他特殊的Bean:这是一个钩子方法。子类可以借助这个方法执行一些特殊的操作,如AbstractRefreshableWebApplicationContext就使用该方法执行初始化ThemeSource的操作;
- 注册事件监听器;
- 初始化所有单实例的Bean,使用懒加载模式的Bean初始化:初始化Bean后,将它们放入spring容器的缓存池中;
- 初始化上下文刷新事件:创建上下文刷新事件,事件广播器负责将这些事件广播到每个注册的事件监听器中。
spring容器从加载配置文件到创建一个完整Bean的作业流程及参与的角色
- ResourceLoader从存储介质中加载Spring配置信息,并使用Resource表示这个配置文件资源;
- BeanDeFinitionReader读取Resource所指向的配置文件资源,然后解析配置文件。配置文件中的每个< bean >解析成一个BeanDeFinition对象,并保存到BeanDeFinitionRegistry中;
- 容器扫描BeanDefintionRegistry中的BeanDefintion,使用Java反射机制自动识别出Bean工厂后处理器(实现beanfactoryPostProcessor接口的Bean),然后调用这些Bean工厂后处理对BeanDeFinitionRegistry中的BeanDeFinition进行加工处理。主要完成一下两项工作:
1). 对使用占位符的< bean >元素标签进行解析,得到最终的配置值。这意味着对一些半成品式的BeanDeFinition对象进行加工处理并得到成品的BeanDeFinition对象;
2). 对BeanDeFinitionRegistry中的BeanDeFinition进行扫描,通过Java反射机制找出所有属性编辑器的Bean(实现java.beans.propertyeditor接口的Bean),并自动将它们注册到spring容器的属性器注册表中(propertyeditorRegistry)。 - spring容器从BeanDeFinitionRegistry中取出加工后的BeanDeFinition,并调用InstantiationStarategy着手进行Bean实例化的工作;
- 在实例化Bean时,spring容器使用BeanWrapper对Bean进行封装。BeanWrapper提供了很多以Java反射机制操作Bean的方法,它将结合该Bean的BeanDefintion及容器中的属性编辑器,完成Bean属性注入工作;
- 利用容器中的Bean后处理器(实现BeanPostProcessor接口的Bean)对己经完成属性设置工作的Bean进行后续加工,直接装配出一个准备就绪的Bean;
小结
spring容器堪称一部设计精密的机器,其内部拥有众多的组件和装置。Spring的高明之处在于,它使用众多接口描绘除了所有的装置的协作蓝图,构建好Spring的骨架,继而通过继承体系层层推演、不断丰富,最终让Spring成为有血有肉的完整的框架。所有在查看Spring框架的源码时,有两条清晰可见的脉络:
接口层清晰地勾勒出Spring框架地高层功能,框架脉络呼之欲出。有了接口层抽象地描述后,不但Spring自己可以提供具体的实现,任何第三方组织也可以提供不同的实现,可以说Spring完善的接口层使框架的扩展性得到了很好的保证。纵向继承体系的逐步发展,分步骤地实现框架地功能,这种实现方案保证了框架功能不会堆积在某些类身上,从而造成过重地代码逻辑负载,框架的复杂度被完美地分解开了。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。