参考资料:
《Spring IoC源码学习:finishBeanFactoryInitialization 详解》
写在开头:本文为个人学习笔记,内容比较随意,夹杂个人理解,如有错误,欢迎指正。
目录
1、finishBeanFactoryInitialization
3、finishBeanFactoryInitialization
2、getMergedLocalBeanDefinition
一、概述
1、finishBeanFactoryInitialization
在IOC核心方法AbstractApplicationContext#refresh()中,经过obtainFreshBeanFactory、invokeBeanFactoryPostProcessors、registerBeanPostProcessors三个前置步骤后,就到了finishBeanFactoryInitialization。finishBeanFactoryInitialization是这四个方法中最复杂也是最重要的,是整个 Spring IoC 核心中的核心,负责将所有剩余的非懒加载单例 bean实例化。除了一些内部的 bean、实现了 BeanFactoryPostProcessor 接口的 bean、实现了 BeanPostProcessor 接口的 bean,其他的非懒加载单例 bean 都会在这个方法中被实例化,并且 BeanPostProcessor 的触发也是在这个方法中。
2、核心概念
(1)、MergedBeanDefinition
在后续流程中我们会接触到getMergedBeanDefinition等方法,个人理解为合并beanDefinition对于一个 bean 定义来说,可能存在以下几种情况:
- 该 BeanDefinition 存在 “父定义”:首先使用 “父定义” 的参数构建一个RootBeanDefinition,然后再使用该 BeanDefinition 的参数来进行覆盖。
- 该 BeanDefinition 不存在 “父定义”,并且该 BeanDefinition的类型是RootBeanDefinition:直接返回该RootBeanDefinition的一个克隆。
- 该 BeanDefinition不存在 “父定义”,但是该 BeanDefinition 的类型不是RootBeanDefinition:使用该BeanDefinition的参数构建一个RootBeanDefinition。
后面两点,主要是因为通常 BeanDefinition 在之前加载到 BeanFactory 中的时候,通常是被封装成 GenericBeanDefinition (当使用xml配置来注册 bean,则该 bean 定义会被封装成GenericBeanDefinition)或 ScannedGenericBeanDefinition(使用<context:component-scan /> + @Compoment时),但是从这边之后 bean 的后续流程处理都是针对 RootBeanDefinition,因此在这边会统一将 BeanDefinition 转换成 RootBeanDefinition。
(2)、FactoryBean
注意和BeanFactory的区别,FactoryBean是利用工厂模式,为所需类提供单实例对象的方法,Spring中,继承了FactoryBean<?>接口的都是工厂Bean,用来为别的类提供单例对象。需要注意的是,FactoryBean在IOC中的beanName会自带“&”前缀,假设我们有Apple类和AppleFactoryBean工厂类,那么getBean("&apple") 获得的是 AppleFactoryBean,而getBean("apple") 获得的则是AppleFactoryBean通过getObject()方法创建的Apple实例
3、finishBeanFactoryInitialization
(1)完成实例化前的准备工作,初始化上下文转换服务器、注册解析器等
(2)冻结bean,防止创建bean实例时被修改,通过限定beanDefinitionNames的方式实现
(3)实例化所有剩余非懒加载的单实例bean
// AbstractApplicationContext.java
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 初始化此上下文的转换服务
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));
}
// 如果beanFactory之前没有注册嵌入值解析器,则注册默认的嵌入值解析器:主要用于注解属性值的解析。
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
@Override
public String resolveStringValue(String strVal) {
return getEnvironment().resolvePlaceholders(strVal);
}
});
}
// 初始化LoadTimeWeaverAware Bean实例对象
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// 冻结所有bean定义,注册的bean定义不会被修改或进一步后处理,因为马上要创建 Bean 实例对象了
beanFactory.freezeConfiguration();
// 实例化所有剩余(非懒加载)单例对象
beanFactory.preInstantiateSingletons();
}
二、preInstantiateSingletons
1、preInstantiateSingletons
(1)创建beanDefinitionNames的副本beanNames用于后续的遍历,以允许init等方法注册新的bean定义,然后遍历beanNames,触发所有非懒加载单例bean的初始化。获取beanName对应的MergedBeanDefinition,将有需要的BeanDefinition进行合并。
(2)过滤出所有非懒加载单例的bean,并判断beanName对应的bean是否为FactoryBean,如不是,则正常通过getBean(beanName)进行实例化,反之,则先通过getBean(beanName)拿到的是FactoryBean的Bean实例,再通过isEagerInit判断是否需要立即初始化,通过的话则依然是调用getBean(beanName)来实例化。
(3)遍历 beanNames,触发所有 SmartInitializingSingleton 的后初始化回调,这是 Spring 提供的一个扩展点,在所有非懒加载单例实例化结束后调用。
// DefaultListableBeanFactory.java
@Override
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}
// 创建beanDefinitionNames的副本beanNames用于后续的遍历,以允许init等方法注册新的bean定义
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
// 遍历beanNames,触发所有非懒加载单例bean的初始化
for (String beanName : beanNames) {
// 获取beanName对应的MergedBeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// bd对应的Bean实例:不是抽象类 && 是单例 && 不是懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 判断beanName对应的bean是否为FactoryBean
if (isFactoryBean(beanName)) {
// 通过beanName获取FactoryBean实例
// 通过getBean(&beanName)拿到的是FactoryBean本身;通过getBean(beanName)拿到的是FactoryBean创建的Bean实例
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
// 判断这个FactoryBean是否希望急切的初始化
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
} else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
// 如果希望急切的初始化,则通过beanName获取bean实例
getBean(beanName);
}
} else {
// 如果beanName对应的bean不是FactoryBean,只是普通Bean,通过beanName获取bean实例
getBean(beanName);
}
}
}
// 遍历beanNames,触发所有SmartInitializingSingleton的后初始化回调
for (String beanName : beanNames) {
// 拿到beanName对应的bean实例
Object singletonInstance = getSingleton(beanName);
// 判断singletonInstance是否实现了SmartInitializingSingleton接口
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
// 触发SmartInitializingSingleton实现类的afterSingletonsInstantiated方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
smartSingleton.afterSingletonsInstantiated();
return null;
}
}, getAccessControlContext());
} else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
2、getMergedLocalBeanDefinition
(1)判断MergedBeanDefinition是否已在缓存中,如存在则直接返回
(2)通过beanName获取对应的BeanDefinition,再调用getMergedBeanDefinition获取MergedBeanDefinition并加入缓存中
// AbstractBeanFactory.java
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// 检查beanName对应的MergedBeanDefinition是否存在于缓存中
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null) {
// 如果存在于缓存中则直接返回
return mbd;
}
// 如果不存在于缓存中
// getBeanDefinition(beanName): 获取beanName对应的BeanDefinition,从beanDefinitionMap缓存中获取
// getMergedBeanDefinition: 根据beanName和对应的BeanDefinition,获取MergedBeanDefinition
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
3、getMergedBeanDefinition
(1)校验beanName对应的MergedBeanDefinition不存在于缓存中。
(2)如果bd的parentName为空,代表bd没有父定义,无需与父定义进行合并操作,也就是bd的MergedBeanDefinition就是bd本身(可能需要转成RootBeanDefinition)。
(2.1)如果bd的类型为RootBeanDefinition,则bd的MergedBeanDefinition就是bd本身,则直接克隆一个副本。
(2.2)否则,将bd作为参数构建一个RootBeanDefinition(bd一般为GenericBeanDefinition或ScannedGenericBeanDefinition)。
(3)bd存在父定义,需要与父定义合并,首先获取父定义的beanName。
(3.1)如果父定义的beanName与该bean的beanName不同,获取父定义的MergedBeanDefinition(因为父定义也可能有父定义,这里实际上是向上递归到最顶层)。
(3.2)如果父定义的beanName与bd的beanName相同,则拿到父BeanFactory。
(3.2.1)如果父BeanFactory是ConfigurableBeanFactory,则通过父BeanFactory获取父定义的MergedBeanDefinition。
(3.2.2)如果父BeanFactory不是ConfigurableBeanFactory,则抛异常。
(3.3)使用父定义pbd构建一个新的RootBeanDefinition对象(深拷贝),并使用bd覆盖父定义
(4)设置scope,并将beanName与mbd放到mergedBeanDefinitions缓存,以便之后可以直接使用。
// AbstractBeanFactory.java
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
throws BeanDefinitionStoreException {
return getMergedBeanDefinition(beanName, bd, null);
}
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, BeanDefinition containingBd)
throws BeanDefinitionStoreException {
// 加锁再进行操作
synchronized (this.mergedBeanDefinitions) {
// 用于存储bd的MergedBeanDefinition,也就是该方法的结果
RootBeanDefinition mbd = null;
if (containingBd == null) {
// 检查beanName对应的MergedBeanDefinition是否存在于缓存中
mbd = this.mergedBeanDefinitions.get(beanName);
}
// 如果beanName对应的MergedBeanDefinition不存在于缓存中
if (mbd == null) {
if (bd.getParentName() == null) {
// 如果bd的parentName为空,代表bd没有父定义,无需与父定义进行合并操作,
// 也就是bd的MergedBeanDefinition就是bd本身(可能需要转成RootBeanDefinition)
if (bd instanceof RootBeanDefinition) {
// 如果bd的类型为RootBeanDefinition,则bd的MergedBeanDefinition就是bd本身,则直接克隆一个副本
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
} else {
// 否则,将bd作为参数,构建一个RootBeanDefinition。
// 正常使用下,BeanDefinition在被加载后是GenericBeanDefinition或ScannedGenericBeanDefinition
mbd = new RootBeanDefinition(bd);
}
} else {
// 否则,bd存在父定义,需要与父定义合并
BeanDefinition pbd;
try {
// 获取父定义的beanName
String parentBeanName = transformedBeanName(bd.getParentName());
// 如果父定义的beanName与该bean的beanName不同
if (!beanName.equals(parentBeanName)) {
// 获取父定义的MergedBeanDefinition(因为父定义也可能有父定义,也就是bd的爷爷定义...)
pbd = getMergedBeanDefinition(parentBeanName);
} else {
// 如果父定义的beanName与bd的beanName相同,则拿到父BeanFactory,
// 只有在存在父BeanFactory的情况下,才允许父定义beanName与自己相同,否则就是将自己设置为父定义
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
// 如果父BeanFactory是ConfigurableBeanFactory,则通过父BeanFactory获取父定义的MergedBeanDefinition
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
} else {
// 如果父BeanFactory不是ConfigurableBeanFactory,则抛异常
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without an AbstractBeanFactory parent");
}
}
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// 使用父定义pbd构建一个新的RootBeanDefinition对象(深拷贝)
mbd = new RootBeanDefinition(pbd);
// 使用bd覆盖父定义
mbd.overrideFrom(bd);
}
// 如果没有配置scope,则设置成默认的singleton
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
}
// 如果containingBd不为空 && containingBd不为singleton && mbd为singleton,则将mdb的scope设置为containingBd的scope
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
// 将beanName与mbd放到mergedBeanDefinitions缓存,以便之后可以直接使用
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
// 返回MergedBeanDefinition
return mbd;
}
}
4、transformedBeanName
将 name 真正解析成真正的 beanName,主要是去掉 FactoryBean 里的 “&” 前缀,和解析别名。
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
String beanName = name;
// 如果beanName带有 "&" 前缀,则去掉
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
return beanName;
}
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
// 将别名解析成真正的beanName
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
5、getMergedBeanDefinition
依然是根据beanName去获取BeanFactory中的MergedBeanDefinition,getMergedLocalBeanDefinition在上文中已经解释过,这里略过。
@Override
public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {
// 获取真正的beanName(解析别名)
String beanName = transformedBeanName(name);
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
// 如果当前BeanFactory中不存在beanName的Bean定义 && 父beanFactory是ConfigurableBeanFactory,
// 则调用父BeanFactory去获取beanName的MergedBeanDefinition
return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
}
// 在当前BeanFactory中解析beanName的MergedBeanDefinition
return getMergedLocalBeanDefinition(beanName);
}
三、isFactoryBean
1、isFactoryBean
(1)拿到真正的beanName(去掉&前缀、解析别名),并尝试从缓存获取Bean实例对象。
(2)beanInstance存在,则直接判断类型是否为FactoryBean,如果不存在,并且beanName在单例对象缓存中,则代表beanName对应的单例对象为空对象,返回false。
(3)如果缓存中不存在此beanName && 父beanFactory是ConfigurableBeanFactory,则调用父BeanFactory判断是否为FactoryBean。
(4)通过MergedBeanDefinition来检查beanName对应的Bean是否为FactoryBean。
// AbstractBeanFactory.java
@Override
public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
// 拿到真正的beanName(去掉&前缀、解析别名)
String beanName = transformedBeanName(name);
// 尝试从缓存获取Bean实例对象
Object beanInstance = getSingleton(beanName, false);
if (beanInstance != null) {
// beanInstance存在,则直接判断类型是否为FactoryBean
return (beanInstance instanceof FactoryBean);
} else if (containsSingleton(beanName)) {
// 如果beanInstance为null,并且beanName在单例对象缓存中,则代表beanName对应的单例对象为空对象,返回false
return false;
}
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
// 如果缓存中不存在此beanName && 父beanFactory是ConfigurableBeanFactory,则调用父BeanFactory判断是否为FactoryBean
return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
}
// 通过MergedBeanDefinition来检查beanName对应的Bean是否为FactoryBean
return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
}
2、getSingleton
(1)从单例对象缓存中获取beanName对应的单例对象,如果单例对象缓存中没有,并且该beanName对应的单例bean正在创建中,则加锁并并行操作。
(2)从早期单例对象缓存中获取单例对象(早期单例对象,是指earlySingletonObjects里的对象,都是通过singletonFactory创建出来的,还未进行属性填充等操作),判断早期单例对象缓存中是否没有,并且允许创建早期单例对象引用,则从单例工厂缓存(singletonFactories)中获取beanName的单例工厂(singletonFactory)。
(3)如果存在单例对象工厂,则通过工厂创建一个单例对象(singletonObject )。将该对象放到早期单例对象缓存中,并移除该beanName对应的单例对象工厂。(因为该单例工厂已经创建了一个实例对象,并且放到earlySingletonObjects缓存了, 因此,后续获取beanName的单例对象,可以通过earlySingletonObjects缓存拿到,不需要在用到该单例工厂)。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从单例对象缓存中获取beanName对应的单例对象
Object singletonObject = this.singletonObjects.get(beanName);
// 如果单例对象缓存中没有,并且该beanName对应的单例bean正在创建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 加锁进行操作
synchronized (this.singletonObjects) {
// 从早期单例对象缓存中获取单例对象(之所称成为早期单例对象,是因为earlySingletonObjects里
// 的对象的都是通过提前曝光的ObjectFactory创建出来的,还未进行属性填充等操作)
singletonObject = this.earlySingletonObjects.get(beanName);
// 如果在早期单例对象缓存中也没有,并且允许创建早期单例对象引用
if (singletonObject == null && allowEarlyReference) {
// 从单例工厂缓存中获取beanName的单例工厂
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 如果存在单例对象工厂,则通过工厂创建一个单例对象
singletonObject = singletonFactory.getObject();
// 将通过单例对象工厂创建的单例对象,放到早期单例对象缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
// 移除该beanName对应的单例对象工厂,因为该单例工厂已经创建了一个实例对象,并且放到earlySingletonObjects缓存了,
// 因此,后续获取beanName的单例对象,可以通过earlySingletonObjects缓存拿到,不需要在用到该单例工厂
this.singletonFactories.remove(beanName);
}
}
}
}
// 返回单例对象
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
4个重要缓存:
- singletonObjects缓存:存放beanName ->bean实例的映射。
- earlySingletonObjects缓存:存放beanName -> bean对象的映射(注意,这里存放的是早期单例 bean 对象,还未进行属性填充、初始化)
- singletonFactories缓存:存放beanName ->单例工厂缓存的映射。
- singletonsCurrentlyInCreation缓存:当前正在创建单例 bean 对象的 beanName 集合。
3、isFactoryBean
protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
// 拿到beanName对应的Bean实例的类型
Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);
// 返回beanType是否为FactoryBean本身、子类或子接口
return (beanType != null && FactoryBean.class.isAssignableFrom(beanType));
}
总结:
本文中主要了解了对于不同的bean的处理步骤,主要分为普通bean和FactoryBean。
普通bean直接调用getBean创建,FactoryBean则需要获取BeanDefinition的 MergedBeanDefinition,最后将BeanDefinition统一转换成 RootBeanDefinition。
bean实例化核心方法getBean会在后续进行整理。