• 前言:在上文bean加载过程中还要一个非常重要的方法没有分析createBean,该方法非常重要,因此特意提出来单独分析。

createBean方法定义在AbstractBeanFactory中:

该方法根据给定的beanName、BeanDefinition和args实例化一个bean对象。所有bean实例的创建都会委托给该方法实现。

AbstractAutowireCapableBeanFactory#createBean

createBean的默认实现在AbstractAutowireCapableBeanFactory类中,代码如下:

 protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd; // Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
// 确保此时的bean已经被解析了
// 如果获取的class属性不为null,则克隆该BeanDefinition,主要是因为动态解析的class无法保存到共享的BeanDefinition
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
} // Prepare method overrides.
try {
// 验证和准备覆盖方法
mbdToUse.prepareMethodOverrides();
} catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
} try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 实例化的前置处理
// 给BeanPostProcessor一个机会用来返回一个代理类而不是真正的实例类
// AOP的功能就是基于这个地方
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 {
// 创建Bean对象
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
} catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
} catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}

分析:

  • 通过resolveBeanClass解析BeanDefinition的class属性。
  • 处理override属性。
  • 通过resolveBeforeInstantiation进行实例化的前置处理。
  • 最后通过doCreateBean创建bean对象。

AbstractBeanFactory#resolveBeanClass

 protected Class<?> resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch)
throws CannotLoadBeanClassException { try {
if (mbd.hasBeanClass()) {
return mbd.getBeanClass();
}
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
} else {
return doResolveBeanClass(mbd, typesToMatch);
}
// ..... 省略异常处理
}

分析:

该方法主要是解析BeanDefinition的class类,如果解析的class类不为空,则将其设置到mbdToUse中,因为动态解析的class无法保存到共享的BeanDefinition中。

AbstractBeanFactory#prepareMethodOverrides

 public void prepareMethodOverrides() throws BeanDefinitionValidationException {
// Check that lookup methods exists.
// 如果方法可以覆盖
if (hasMethodOverrides()) {
// 得到覆盖方法
Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
// 同步
synchronized (overrides) {
// 循环调用 prepareMethodOverride进行覆盖准备
for (MethodOverride mo : overrides) {
prepareMethodOverride(mo);
}
}
}
}

分析:

bean标签中的lookup-method和replace-method属性就是放在BeanDefinition的methodOverrides属性中(关于这两个属性的分析后续再来分析),这里就是对methodOverrides属性进行处理,动态为当前bean生产代理并使用对应的拦截器为bean做增强处理。

上述处理逻辑就是循环获取MethodOverride属性,然后调用prepareMethodOverride进行处理。

 // AbstractBeanDefinition
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
if (count == 0) {
throw new BeanDefinitionValidationException(
"Invalid method override: no method with name '" + mo.getMethodName() +
"' on class [" + getBeanClassName() + "]");
} else if (count == 1) {
// Mark override as not overloaded, to avoid the overhead of arg type checking.
mo.setOverloaded(false);
}
}

分析:

根据方法名,从class中获取该方法名的个数:

  • 如果方法名个数为0,则抛出BeanDefinitionValidationException异常,原因其实很简单:通过方法名去查找,而又没有找到,则说明有问题,抛出异常。
  • 如果方法名个数为1,则设置该方法未被重载(overloaded属性模式为true)。如果一个类存在多个重载方法,在方法调用的时候还需根据参数类型来判断到底重载的是哪个方法,这里通过count=1,来表示该方法未被重载,在调用的时候可以直接找方法而不需要进行方法参数的校验,相当于一个小小的优化,提升后面调用函数的速度。

AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation

 protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
// 如果bean不是应用系统的,有BeanPostProcessor
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 前置处理
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 后置处理
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}

分析:

通过applyBeanPostProcessorsBeforeInstantiation和applyBeanPostProcessorsAfterInitialization对bean实例化前进行前置与后置处理。如果返回了代理对象,则直接返回结果,Spring后续实现AOP就是基于这个地方进行的判断。

前置处理与后置处理后续再具体进行分析。

AbstractAutowireCapableBeanFactory#doCreateBean

 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException { // Instantiate the bean.
// BeanWrapper是对Bean的包装,其接口中所定义的功能很简单包括设置获取被包装的对象、获取被包装bean的属性描述器
BeanWrapper instanceWrapper = null;
// 如果是单例模型,则从未完成的FactoryBean缓存中删除
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
// 使用合适的实例化策略来创建新的实例:工厂方法、构造函数自动注入、简单初始化
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 包装的对象实例
final Object bean = instanceWrapper.getWrappedInstance();
// 包装的实例对象的类型
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
} // Allow post-processors to modify the merged bean definition.
// 先做同步,然后判断是否有后置处理
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 后置处理修改BeanDefinition
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
} // Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 解决单例模式的循环依赖 // 单例模式 运行循环依赖
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));// 当前单例bean是否正在被创建
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 提前将创建的bean实例加入到singletonFactories中
// 为了后期避免循环依赖
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
} // Initialize the bean instance.
// 开始初始化bean实例对象
Object exposedObject = bean;
try {
// 对bean进行填充,主要是进行属性注入,其中,可能存在依赖于其他bean的属性,则会递归初始化依赖bean
populateBean(beanName, mbd, instanceWrapper);
// 进行bean初始化
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);
}
} // 循环依赖处理
if (earlySingletonExposure) {
// 获取earlySingletonReference
Object earlySingletonReference = getSingleton(beanName, false);
// 只有在循环依赖的情况下,earlySingletonReference才不会为null
if (earlySingletonReference != null) {
// 如果exposedObject没有在初始化方法中改变,也就是没有被增强
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
} 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);
}
}
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.");
}
}
}
} // Register bean as disposable.
try {
// 注册bean
registerDisposableBeanIfNecessary(beanName, bean, mbd);
} catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
} return exposedObject;
}

分析:

如果没有代理对象,则会进行bean对象的创建。

  • 如果BeanDefinition为单例模式,首先从FactoryBean缓存中删除该beanName的缓存。
  • 调用createBeanInstance方法创建一个BeanWrapper对象。
  • 调用applyMergedBeanDefinitionPostProcessors对BeanDefinition进行后置处理
  • 进行单例模式的循环依赖处理。
  • 调用populateBean进行bean属性填充。
  • 调用initializeBean进行bean初始化。
  • 进行依赖检查。
  • 最后注册bean。

上述列出了创建bean对象的主要步骤,过程还是比较复杂的,下面一一进行分析。主要关注点createBeanInstance、populateBean、initializeBean三个函数。

AbstractAutowireCapableBeanFactory#createBeanInstance

 protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
// 解析bean,将bean类名解析为class引用
Class<?> beanClass = resolveBeanClass(mbd, beanName); if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
} // 如果存在supplier回调,则使用给定的回调方法初始化策略
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
} // 使用FactoryBean的factor-method来创建bean,支持静态工厂和实例工厂
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
} // Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
// 做同步
synchronized (mbd.constructorArgumentLock) {
// 如果已缓存的解析构造函数或者工厂方法不为null,则可以利用构造函数解析
// 因为需要根据参数确认到底使用哪个构造函数,该过程比较消耗性能,所以采用缓存机制
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 已经解析好了,直接注入即可
if (resolved) {
// autowire自动注入,调用构造函数自动注入
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
} else {
// 使用默认构造函数构造
return instantiateBean(beanName, mbd);
}
} // Need to determine the constructor...
// 确定解析的构造函数
// 主要是检查已经注册的SmartInstantiationAwareBeanPostProcessor
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 确定构造方法进行bean创建
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
} // 有参数,又没有获取到构造方法,则只能调用无参构造方法来创建实例
// 这是一个兜底的方法
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}

分析:

bean的实例化一个比较复杂的过程。

  • 如果设置Supplier回调,则调用obtainFromSupplier方法进行初始化。
  • 如果存在工厂方法,则使用工厂方法进行初始化。
  • 先判断缓存中是否存在构造函数,如果存在,则根据是否使用自动注入,还是默认的构造函数进行bean对象的初始化。
  • 如果缓存中不存在,则需先判断到底使用哪个构造函数来完成解析工作。
  • 如果上述条件还是不满足,则使用无参构造方法来创建实例。

#1.如果设置Supplier回调,则使用obtainFromSupplier方法进行初始化。

首先了解下Supplier接口(java.util.function):

  • Supplier接口仅有一个功能性的get()方法,该方法会返回一个<T>类型的对象,有点类似工厂方法。
  • 如果我们在创建BeanDefinition的时候设置了Supplier参数,那么其他的构造器或者工厂方法就没有作用了。
  • AbstractBeanDefinition中提供了设置Supplier的入口:

AbstractAutowireCapableBeanFactory#obtainFromSupplier

 protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
// 获得原创建的Bean的对象名
String outerBean = this.currentlyCreatedBean.get();
// 设置新的Bean对象名到currentlyCreatedBean中
this.currentlyCreatedBean.set(beanName);
Object instance;
try {
// 调用Supplier的get(),返回一个Bean对象
instance = instanceSupplier.get();
} finally {
// 设置原创建的Bean对象名到currentlyCreatedBean中
if (outerBean != null) {
this.currentlyCreatedBean.set(outerBean);
} else {
this.currentlyCreatedBean.remove();
}
}
// 创建BeanWrapper对象
BeanWrapper bw = new BeanWrapperImpl(instance);
// 初始化BeanWrapper
initBeanWrapper(bw);
return bw;
}

分析:

  • 调用Supplier#get方法,获取一个Bean实例对象。
  • 根据该实例对象构建BeanWrapper对象。
  • 最后初始化该对象。

如果存在工厂方法,则会调用工厂方法来完成bean的初始化工作,该方法实现比较长,并且细节复杂,由于篇幅原因放在下篇文章中解析。

总结

这里仅仅分析了doCreateBean方法中的一点点内容,如果存在Supplier回调,则会直接通过Supplier来创建Bean对象,构造函数和工厂方法则失效,下面将对分析使用工厂方法实例化Bean对象的过程。


by Shawn Chen,2019.04.23,下午。

【spring源码分析】IOC容器初始化(八)的更多相关文章

  1. SPRING源码分析:IOC容器

    在Spring中,最基本的IOC容器接口是BeanFactory - 这个接口为具体的IOC容器的实现作了最基本的功能规定 - 不管怎么着,作为IOC容器,这些接口你必须要满足应用程序的最基本要求: ...

  2. Spring源码解析-ioc容器的设计

    Spring源码解析-ioc容器的设计 1 IoC容器系列的设计:BeanFactory和ApplicatioContext 在Spring容器中,主要分为两个主要的容器系列,一个是实现BeanFac ...

  3. spring源码分析---IOC(1)

    我们都知道spring有2个最重要的概念,IOC(控制反转)和AOP(依赖注入).今天我就分享一下spring源码的IOC. IOC的定义:直观的来说,就是由spring来负责控制对象的生命周期和对象 ...

  4. spring 源码之 ioc 容器的初始化和注入简图

    IoC最核心就是两个过程:IoC容器初始化和IoC依赖注入,下面通过简单的图示来表述其中的关键过程:

  5. Spring源码阅读-IoC容器解析

    目录 Spring IoC容器 ApplicationContext设计解析 BeanFactory ListableBeanFactory HierarchicalBeanFactory Messa ...

  6. Spring 源码剖析IOC容器(一)概览

    目录 一.容器概述 二.核心类源码解读 三.模拟容器获取Bean ======================= 一.容器概述 spring IOC控制反转,又称为DI依赖注入:大体是先初始化bean ...

  7. Spring源码解析-IOC容器的实现

    1.IOC容器是什么? IOC(Inversion of Control)控制反转:本来是由应用程序管理的对象之间的依赖关系,现在交给了容器管理,这就叫控制反转,即交给了IOC容器,Spring的IO ...

  8. Spring源码解析-IOC容器的实现-ApplicationContext

    上面我们已经知道了IOC的建立的基本步骤了,我们就可以用编码的方式和IOC容器进行建立过程了.其实Spring已经为我们提供了很多实现,想必上面的简单扩展,如XMLBeanFacroty等.我们一般是 ...

  9. Spring源码之IOC容器创建、BeanDefinition加载和注册和IOC容器依赖注入

    总结 在SpringApplication#createApplicationContext()执行时创建IOC容器,默认DefaultListableBeanFactory 在AbstractApp ...

  10. 【spring源码分析】IOC容器初始化(总结)

    前言:在经过前面十二篇文章的分析,对bean的加载流程大致梳理清楚了.因为内容过多,因此需要进行一个小总结. 经过前面十二篇文章的漫长分析,终于将xml配置文件中的bean,转换成我们实际所需要的真正 ...

随机推荐

  1. java中强大的免费的集成开发环境(IDE)eclipse的使用技巧及注意事项

    1调整字体,window->prefernce->Appereance->colors and fonts->Basic->Text font双击即可进行编辑 2.设置行 ...

  2. Winform自定义无边框窗体

    目的: 1.将窗体设置成无边框,如下面效果图 2.该无边框窗体添加了窗体放大.缩小(可以根据需要只能横向放大缩小  或者  竖向放大缩小)的功能 Point vPoint = new Point((i ...

  3. MongoDB 4.0 开发环境搭建集群

    环境准备 Liunx 服务器一台 以下示例为单机版安装集群, 没有分片 MongoDB 安装 1.下载 MongoDB tgz 安装包: 可以从下载中心下载: https://www.mongodb. ...

  4. 【死磕 Spring】—– IOC 之解析Bean:解析 import 标签

    原文出自:http://cmsblogs.com 在博客[死磕Spring]----- IOC 之 注册 BeanDefinition中分析到,Spring 中有两种解析 Bean 的方式.如果根节点 ...

  5. Spring Bean 生命周期测试

    本文代码GitHub地址 Bean的生命周期是开始创建到销毁的过程.需要实现相关的类BeanNameAware   ,DisposableBean, InitializingBean ,并注册Inst ...

  6. css垂直居中方法总结

    在网页布局中,我们往往会遇到下图所示的场景,让小图标和文字对齐 可能有的小伙伴会说,这个简单,直接给小图标设置左浮动来实现. 这样做是可以的,但不推荐,毕竟浮动是会影响布局的,能少用还是少用. 以前遇 ...

  7. @vue/cli 3.0 使用 svg-sprite-loader 加载本地 SVG 文件

    目录 @vue/cli 3.0 使用 svg-sprite-loader 加载本地 SVG 文件 运行 使用 配置 svg-sprite-loader 调用当前环境下的颜色 props @vue/cl ...

  8. javascript放大镜效果

    JS实现放大镜效果 首先我们先设想一下放大镜效果 1.当鼠标进入小盒子的时候,把大图片显示出来 2.当指定移动区域的时候,显示当前放大区域(放大效果) 3.鼠标移除我们让它消失 一.实现页面布局HTM ...

  9. qml demo分析(threading-线程任务)

    一.关键类说明 qml内置了WorkerScript组件,该组件有一个source属性,可以加载js文件,含有一个名为message的信号,意味着他有一个默认的onMessage槽函数,除此之外他还有 ...

  10. SpinnerViewPop【PopWindow样式(单选)、Dialog样式(单选+多选)的下拉菜单】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 对下拉菜单的文本区域和列表区域进行了封装.包括两种展现方式:popwindow(单选).dialog(单选+多选) 因为该封装需要在 ...