• 前言:在上文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. lombok的安装

    Lombok简介 Lombok是一个可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很臃肿的Java代码的工具,通过使用对应的注解,可以在编译源码的时候生成对应的方法.官方地址:https:/ ...

  2. SLA服务可用性怎么达到?

    SLA:服务等级协议(简称:SLA,全称:service level agreement).是在一定开销下为保障服务的性能和可用性,服务提供商与用户间定义的一种双方认可的协定.通常这个开销是驱动提供服 ...

  3. Luogu P5292 [HNOI2019]校园旅行

    非常妙的一道思博题啊,不愧是myy出的题 首先我们考虑一个暴力DP,直接开一个数组\(f_{i,j}\)表示\(i\to j\)的路径能否构成回文串 考虑直接拿一个队列来转移,队列里存的都是\(f_{ ...

  4. gulp源码解析(一)—— Stream详解

    作为前端,我们常常会和 Stream 有着频繁的接触.比如使用 gulp 对项目进行构建的时候,我们会使用 gulp.src 接口将匹配到的文件转为 stream(流)的形式,再通过 .pipe() ...

  5. Workbooks 对象的 Open 方法参数说明

    Workbooks 对象的 Open 方法参数说明 打开一个工作簿. expression.Open(FileName, UpdateLinks, ReadOnly, Format, Password ...

  6. dubbo 序列化机制之 hessian2序列化实现原理分析

    对于远程通信,往往都会涉及到数据持久化传输问题.往大了说,就是,从A发出的信息,怎样能被B接收到相同信息内容!小点说就是,编码与解码问题! 而在dubbo或者说是java的远程通信中,编解码则往往伴随 ...

  7. 让你用 Chrome 上网快到想哭:Vimium

    Chrome 已经成了很多人的主力浏览器,你可能被它的简洁快速所吸引,但它日益丰富的「扩展」,你可能从来都没有接触过,而事实上,很多扩展可以挖掘出 Chrome 的潜能,让它变得前所未有的强大.有哪些 ...

  8. 如何在ASP.NET Core中使用JSON Patch

    原文: JSON Patch With ASP.NET Core 作者:.NET Core Tutorials 译文:如何在ASP.NET Core中使用JSON Patch 地址:https://w ...

  9. Cache【硬盘缓存工具类(包含内存缓存LruCache和磁盘缓存DiskLruCache)】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 内存缓存LruCache和磁盘缓存DiskLruCache的封装类,主要用于图片缓存. 效果图 代码分析 内存缓存LruCache和 ...

  10. NormalDialogFragmentDemo【普通页面的DialogFragment】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 该Demo主要演示DialogFragment作为普通页面,显示全屏和状态栏下方的效果以及动画效果. 效果图 代码分析 @Overr ...