在前篇中我们已经对Spring容器中的AbstractBeanFactory类作了简单的介绍。当Spring容器使用BeanFactory获取单例bean时,会从缓存中获取已经注册的bean实例,如果还未注册会创建该bean实例。对于原型bean,Spring容器总是会创建一个新的bean实例。
在本篇中我们将对AbstractBeanFactory类中createBean方法做简单的分析。在AbstractBeanFactory类中该方法是一个抽象方法,它由AbstractBeanFactory的子类AbstractAutowireCapableBeanFactory实现。我们来看看该类和其中的createBean方法。
AbstractAutowireCapableBeanFactory
我们先来看一下AbstractBeanFactory的实现类们:
其中XmlBeanFactory类在Spring3.1后已经被摒弃,DefaultListableBeanFactory类是ListableBeanFactory接口和BeanDefinitionRegistry接口的默认实现类,也是Spring容器中核心的BeanFactory之一。
我们主要看AbstractAutowireCapableBeanFactory类,它主要实现了bean的创建、属性注入、初始化等功能,它的核心方法是createBean和doCreateBean方法。
createBean
AbstractAutowireCapableBeanFactory类中的createBean方法是对AbstractBeanFactory类中的createBean抽象方法的实现。具体源码如下(简化日志输出):
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 获取BeanDefinition(省略创建的日志)
RootBeanDefinition mbdToUse = mbd;
// 确保bean的Class类型已经被解析
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
// 如果bean的类型是动态的,则拷贝bean的BeanDefinition
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// 验证和准备BeanDefinition中的重写方法
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// before-instantiation处理,在实例化之前检查是否有代理类可以返回
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 实际的创建方法
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
// 省略正在创建的日志输出
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// 先前在创建bean的创建上下文时已经检测到异常,或者将非法singleton状态传递给DefaultSingletonBeanRegistry。
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
从上面的代码中我们可以看到,createBean在创建bean时首先会检查bean的类型是否已经被正确的解析,并对动态类型的bean作特殊处理。然后会尝试获取目标bean的代理类,最后再进行实际的创建工作。
doCreateBean
接下来我们看看最重要的doCreateBean方法到底干了哪些事,代码如下(省略日志输出):
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
/// 实例化bean,并用wrapper包装
BeanWrapper instanceWrapper = null;
// 从实例缓存中获取
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
// 缓存中没有则实例化
if (instanceWrapper == null) {
// 实际的实例化操作
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 获取实例化后的bean实例
final Object bean = instanceWrapper.getWrappedInstance();
// 获取bean的类型
Class<?> beanType = instanceWrapper.getWrappedClass();
// 类型不为空则注入到BeanDefinition中的解析类型中
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 对MergedBeanDefinition进行PostProcessors处理,该处理可以允许在bean实例化后对bean的BeanDefinition进行修改
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
// 已处理标志为true
mbd.postProcessed = true;
}
}
// 判断是否要提前暴露
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
// 如果要
if (earlySingletonExposure) {
// 省略提前引用的日志
// 添加可以获取提前引用的单例工厂
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 初始化bean实例
Object exposedObject = bean;
try {
// 属性注入
populateBean(beanName, mbd, instanceWrapper);
// 初始化bean(setBeanName,setBeanClassLoader等)
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
// 如果要提前暴露单例bean
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
// 能获取到
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
// 检查依赖该bean的bean还都不存在(正常情况应该还不存在)
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
// 如果已存在,抛出异常(意味着别的bean依赖的bean不对或不是最终版本)
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// 尝试注册disposable的bean(即destroy方法)
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
// 返回创建完成的bean
return exposedObject;
}
从上面的代码中,我们可以看到doCreateBean方法主要做了以下两件事:
1.实际的完成了bean的实例化,属性的注入和初始化操作,并尝试注册可注销的bean。
2.针对允许提前引用的情况,对bean做提前暴露的操作。
populateBean方法能对实例化后的bean的属性进行注入。
initializeBean方法能对实现了BeanNameAware,BeanClassLoaderAware和BeanFactoryAware接口的bean的name,classLoader和factory实现注入。这三个接口与Spring容器中bean生命周期的前三个部分相对应。并且在初始化之前和初始化之后都会调用相应的BeanPostProcessor。这里不再累述。
总结
通过上述源码,我们大致可以看出Spring容器中bean的实际创建过程,以及bean的提前暴露以解决循环引用问题的整个逻辑。
结合前篇,我们可以看到,AbstractAutowireCapableBeanFactory类与AbstractBeanFactory类通过getBean和createBean方法,实现了Spring容器创建和获取bean的大部分逻辑。在以后的博客中,我可能会对还有一个重要步骤,即Spring容器如何注册bean进行一下简单的介绍。