在Spring容器中,Bean的生命周期都是交由BeanFactory接口以及它的实现类处理的。
AbstractBeanFactory是BeanFactory接口的一个默认抽象实现类,他实现了BeanFactory接口的方法,并在此基础上进行了扩展。
Spring规定BeanFactory接口的实现类应该能尽可能的支持bean的标准生命周期。
一个Bean的标准生命周期如下(图片侵删):
我们也可以在Spring的官方文档和源码的注释中看到更为精确的Bean的标准生命周期以及它的顺序。
而一个Bean的创建过程将会贯穿除了destroy的整个生命周期(但非规定的全部)。
AbstractBeanFactory
本文将分两篇。前篇从AbstractBeanFactory类入手,简单的讲一讲Spring容器中Bean的部分创建过程。
doGetBean
首先来看AbstractBeanFactory类中的doGetBean方法,它是该类中一系列public的getBean方法的内部方法。该方法会根据Bean的类名、Class和构造参数等参数返回特定的Bean,这些Bean可以来自不同的配置源配置的Bean或者Spring容器本身的Bean。并且,根据是否已经注册Bean和Bean的类型选择是否创建该Bean,具体源码如下(代码较长,省略了其中的日志输出代码)。
// 传入bean类名和bean的Class类型以及构造参数
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 将类名转化为全限定名
final String beanName = transformedBeanName(name);
Object bean;
// 检查缓存中是否已经存在注册的单例bean
// (单例bean能提前注册消除bean注册的循环引用问题)
Object sharedInstance = getSingleton(beanName);
// 如果存在则获取该bean
if (sharedInstance != null && args == null) {
// 省略部分日志(单例bean是否已在创建中)
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 如果不存在
else {
// 首先判断该bean是否在正在创建中或循环引用
// 判断原型bean是否在创建中,若是则抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 检查父BeanFactory中,该bean的BeanDefine是否已经注册
// parentBeanFactory为该bean目前对应的BeanFactory的父BeanFactory
BeanFactory parentBeanFactory = getParentBeanFactory();
// 在父BeanFactory中找不到该bean的BeanDefine
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 继续检查父类BeanFactory的BeanDefine
String nameToLookup = originalBeanName(name);
// 已经到了AbstractBeanFactory类,继续检查
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
// 分情况,有参无参作不同检查
else if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 获取并检查bean的BeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 保证bean依赖的bean已经初始化
// 从BeanDefinition获取依赖的bean名
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 判断是否存在循环依赖,是则抛出异常
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 注册需要依赖的bean
registerDependentBean(dep, beanName);
try {
// 创建(初始化)该Bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 创建bean.
// 如果是单例的bean
if (mbd.isSingleton()) {
// 创建bean(前面已经检查过还未注册过该bean)
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建bean的方法,后篇会详述
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// 出现异常则显式注销该bean
destroySingleton(beanName);
throw ex;
}
});
// 获取该bean实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 如果是原型的bean
else if (mbd.isPrototype()) {
// 直接创建新的实例
Object prototypeInstance = null;
try {
// 将bean名存入原型bean的“正在创建”缓存set中
beforePrototypeCreation(beanName);
// 创建bean
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 清除该bean的“正在创建”缓存
afterPrototypeCreation(beanName);
}
// 获取该bean的实例
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
// 其他情况
else {
// 从BeanDefinition中获取bean的scope
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
// scope为空则抛出异常
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
// 默认按原型bean处理
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
// 获取bean实例
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 确认bean的实例类型与所需的类型是否一致
// 如果不是则需要转换
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
// 强转bean类型
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
// 失败则抛出异常
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
// 失败则抛出异常
catch (TypeMismatchException ex) {
// 输出日志并抛出异常
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
// 返回bean实例
return (T) bean;
}
从上面的源码中可以看到,Spring获取bean的整个过程主要分为两步:
1.如果已经注册且为单例的bean,直接从缓存中获取实例。
2.如果没有注册或为其他形式的bean,先检查是否正在创建,再根据不同类型创建相应bean,最后将获取的object实例强转为相应类型的bean。
重要方法
下面我们来看几个源码中比较重要的方法
在这之前,我们先来看看AbstractBeanFactory的类图
其中FactoryBeanRegistrySupport类主要用于bean的注册和创建。
源码中频繁出现了两个方法,getSingleton和getObjectForBeanInstance。
getSingleton方法是DefaultSingletonBeanRegistry类中的几个重载方法,主要用于单例bean的创建注册和获取。
getObjectForBeanInstance方法是AbstractBeanFactory类内的方法,调用的内部方法也来自继承的FactoryBeanRegistrySupport类,它能从factoryBeanObjectCache缓存中获取到已经注册的bean实例。本文不对它进行过多描述,感兴趣的小伙伴可以直接看源码。
下面我们主要来看看getSingleton方法。
getSingleton
DefaultSingletonBeanRegistry中有三个重载的getSingleton方法,其中两个能够返回已经注册的bean,且能返回正在创建的bean。
这个措施能解决bean注册时会遇到的循环引用问题。两个方法的代码如下:
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从缓存中获取单例bean
Object singletonObject = this.singletonObjects.get(beanName);
// 如果获取不到但又是正在创建的bean则从earlySingletonObjects中获取
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 从earlySingletonObjects缓存中获取
singletonObject = this.earlySingletonObjects.get(beanName);
// 如果获取不到且允许提前引用(默认true),则将bean存于earlySingletonObjects中
if (singletonObject == null && allowEarlyReference) {
// singletonFactory是注册的单例工厂
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
// 将bean以beanName的形式存入earlySingletonObjects缓存
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
从上面的代码我们可以看到,这两个重载的getSingleton方法不参与bean的创建,它只从缓存中拿。且当bean处于创建状态时,能够提前暴露该bean。这能解决单例bean之间的循环引用问题:
当A依赖B,B同时依赖A时,A在创建时需要B已经创建,而B创建时也需要A已经创建。如果没有提前引用的措施,AB在创建时会陷入无限等待对方的情况中
另一个重载的getSingleton方法则可以创建bean,代码如下(简化了日志输出代码):
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// 检查类名是否为空
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
// 从缓存中获取bean实例
Object singletonObject = this.singletonObjects.get(beanName);
// 如果不存在
if (singletonObject == null) {
// 如果bean的factory正在注销则报错
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
// 将bean加入“正在创建”缓存中
beforeSingletonCreation(beanName);
// 初始化参数
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 创建bean,AbstractBeanFactory类中采用lambda的的方式实现,实际的核心是AbstractBeanFactory的createBean方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// 将bean移除“正在创建”缓存
afterSingletonCreation(beanName);
}
// 完成注册,将bean加入已注册beans中,移除中间缓存
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
从上面的代码中我们可以看出,这个重载的getSingleton方法相较于其他两个方法,多了创建bean的步骤。这里不做过多解释。
总结
通过上述源码,我们大致可以看出Spring容器中bean的创建过程。与此同时,Spring还用了提前引用的方式,来解决bean创建过程中的循环引用死锁问题。
创建bean时的一个核心方法是createBean,它是AbstractBeanFactory类中的一个抽象方法,AbstractBeanFactory的子类将实现这个方法。DefaultListableBeanFactory类和AbstractAutowireCapableBeanFactory类是AbstractBeanFactory类的两个子类。之后的博客中我会从这两个类入手,继续从源码的角度简单分析一下这个createBean方法。