标题中强调指出ApplicationContext,是因为使用Spring框架有两种方式:BeanFactory和ApplicationContext,代码如下:
// beanFactory方式
@Test
public void beanFactoryTest() {
Resource classPathResource = new ClassPathResource("applicationContext.xml");
BeanFactory xmlBeanFactory = new XmlBeanFactory(classPathResource);
}
// ApplicationContext方式
@Test
public void awareTest() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"applicationContext.xml");
}
它们的区别是:BeanFactory在初始化的时候,不会加载任何bean实例;而ApplicationContext初始化的时候,会提前加载xml中配置的所有单例bean。
我们本篇的目的,是为了探究ApplicationContext初始化的时候,在哪个步骤加载这些单例bean的。
以下是ApplicationContext初始化的经典入口代码:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 准备刷新的上下文环境
prepareRefresh();
// 2. 初始化BeanFactory,并进行XML文件的加载
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 对BeanFactory进行各种功能填充
prepareBeanFactory(beanFactory);
try {
// 4. 子类覆盖犯法做额外的处理
postProcessBeanFactory(beanFactory);
// 5. 调用BeanFactory后处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册bean后处理器,在调用getBean的时候回调这些bean后处理器的方法
registerBeanPostProcessors(beanFactory);
// 7. 为上下文初始化Message源
initMessageSource();
// 8. 初始化事件多播器
initApplicationEventMulticaster();
// 9. 留给子类初始化其他bean
onRefresh();
// 10. 注册监听器
registerListeners();
// 11. 初始化剩下的单例Bean(非惰性的)
finishBeanFactoryInitialization(beanFactory);
// 12. 最后一步,发布通知事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 销毁已经创建的单例,以避免挂起资源。
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();
}
}
}
与本文相关的代码在第11步,加载剩下的单例Bean。我们由此入口来开始分析~
进入到AbstractApplicationContext类的finishBeanFactoryInitialization方法
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 1.初始化此上下文的ConversionService
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// 2.注册嵌入式值解析器(用于解析注解标注的属性值)
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// 3.初始化LoadTimeWeaverAware
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// 4.停止使用临时类加载器进行类型匹配
beanFactory.setTempClassLoader(null);
// 5.允许缓存所有bean定义元数据,而不期望有进一步的更改。
beanFactory.freezeConfiguration();
// 6.实例化所有剩余的(非lazy-init)单例。
beanFactory.preInstantiateSingletons();
}
前面几个步骤看不懂没关系,我们重点在第6步,实例化所有非懒加载的单例Bean
懒加载的意思就是,容器启动时要不要加载某个bean,可以通过bean标签中的lazy-init属性配置,默认值为false,即非懒加载(容器启动就加载该bean)
<bean id="person" class="com.kaka.spring.beans.Person" lazy-init="true"/>
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 1. 实例化所有非懒加载的单例Bean
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 1.1 FactoryBean类型的bean
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
// 1.2 其他类型的bean
getBean(beanName);
}
}
}
// 2. 回调SmartInitializingSingleton类型Bean的afterSingletonsInstantiated方法
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
以上代码来自于DefaultListableBeanFactory类的preInstantiateSingletons方法。看着代码量挺多,其实就干了两件事儿:
实例化bean的逻辑都在上面的getBean方法中,里面无非是创建了一个Bean实例、给Bean实例填充属性信息、调用bean实例的初始化方法等等,这些不是本章讨论的重点。
其实到这儿就结束了,从中我们可以了解到以下几点
/** List of bean definition names, in registration order */
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
@Component
public class MySmartInitializingSingleton implements SmartInitializingSingleton {
@Override
public void afterSingletonsInstantiated() {
System.out.println("所有的bean都初始化完成了...");
}
}