Spring容器启动和初始化过程实际上可以分为两个阶段,第一个阶段是容器的初始化,包括容器的创建,bean配置文件读取,解析和BeanDefinition的生成及注册。第二个阶段是bean的实例化,从beanDefinition到bean实例的生成,包括aop的切入等。
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
concurrentTemplate = (AbstractConcurrentTemplate) context.getBean("tairConcurrentTemplate");
上面简单两行,已经包括了Spring的初始化和实例化过程。
Spring中Bean的实例化的触发时机包括主要两类,一步是在初始化结束后,一个是getBean触发时。
bean的实例化过程实际上在AbstractApplicationContext.refresh()时就开始了,具体的入口为:refresh->finishBeanFactoryInitialization->beanFactory.preInstantiateSingletons(),preInstantiateSingletons的实现在DefaultListableBeanFactory类中。
DefaultListableBeanFactory中preInstantiateSingletons的具体逻辑为:
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isInfoEnabled()) {
this.logger.info("Pre-instantiating singletons in " + this);
}
synchronized (this.beanDefinitionMap) {
for (Iterator it = this.beanDefinitionNames.iterator(); it.hasNext();) {
String beanName = (String) it.next();
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
if (factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit()) {
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
}
}
}
遍历beanDefinitionNames链表,这里面按照注册顺序保存了bean的名字
1. AbstractBeanFactory.getMergedLocalBeanDefinition,根据bean名字获取merge后的BeanDefinition,这里merge的内容包括:parent Bean的内容,该方法的具体逻辑是:
1.1 先从mergeBeanDefinition缓存中取,如果能取到,说明前面已经merge过,无须再merge,直接返回。
1.2 根据bean的配置信息,若该bean,指定了parent参数,则获取parentName。
若parentName和当前beanName相同,则直接在父容器中获取parentBean对应的mergeBeanDefinition。否则判断当前容器中是否有parentName对应的bean存在,有则从当前容器中取得parentBeanName的mergeBeanDefinition,否则也从父容器中获取。这里实际上是递归调用,如果最终都无法找到,那么只能报错了。这里的merge实际上是深度拷贝,先拷贝parentBean的mergeBeanDefinition,然后再用当前bean中定义的属性覆盖掉部分属性(overrideFrom)。
1.3 获取beanDefinition后,将其缓存起来,便于后面直接从缓存中获取。
2. 获取得到beanDefinition之后,判断当前bean是否满足:非abstract,isSingleton,且没有指定lazyInit,若不满足,则跳过实例化。
3. 判断当前bean是否是FactoryBean,若是,则3.1,否则3.2
3.1 对于FactoryBean,现在bean前面加上&号,实例化FactoryBean。若是SmartFactoryBean,且isEgerInit(),则实例化由该factoryBean生成的bean。
从这里可以知道:
对于singleton域的FactoryBean(非SmartFactoryBean)类型的bean,在初始化结束后只会实例化工厂bean自身。为了满足一些特殊情况,spring中提供了SmartFactoryBean接口。
3.2 对于普通bean,直接实例化。
从上面可以看到,实例化的方法的真正入口还是getBean。