在Spring源码系列:依赖注入(一)(AbstractBeanFactory-getBean)最后说道getBean是依赖注入的起点,bean的创建都是通过createBean来完成具体的创建的。createBean的具体实现是在AbstractAutowireCapableBeanFactory中的。本篇就捋一捋这个方法看下bean的创建过程。

这个方法是AbstractAutowireCapableBeanFactory这个类的中心方法,其作用就是创建一个bean实例,填充bean实例,后置处理等。

在createBean中主要做了三件事:

  • 判断需要创建的Bean是否可以实例化,这个类是否可以通过类装载器来载入
  • 是否配置了后置处理器相关处理(如果配置了则返回一个代理)
  • 创建Bean

具体来看方法:

protected Object createBean(String beanName, RootBeanDefinition mbd, 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<?> 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) {//异常:Validation of method overrides failed}try {// Give BeanPostProcessors a chance to return a proxy instead of the target //bean instance.//是否配置了后置处理器相关处理(如果配置了则返回一个代理)Object bean = resolveBeforeInstantiation(beanName, mbdToUse);if (bean != null) {return bean;}}catch (Throwable ex) {//异常:BeanPostProcessor before instantiation of bean failed}//创建BeanObject beanInstance = doCreateBean(beanName, mbdToUse, args);if (logger.isDebugEnabled()) {logger.debug("Finished creating instance of bean '" + beanName + "'");}return beanInstance;
}
复制代码

从上面的代码中可以看到,创建bean是交给doCreateBean方法来创建的。继续看doCreateBean这个方法: (这里面涉及到一个BeanWrapper这个接口,小伙伴可以移步了解一下《Spring源码系列:BeanWrapper》)

代码 1:

// 用BeanWrapper来持有创建出来的Bean对象
BeanWrapper instanceWrapper = null;
//如果是单例的话,则先把缓存中的同名bean清除
if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
//实际创建的交给createBeanInstance来完成,
//bean的生成,这里会使用默认的类生成器,包装成BeanWrapperImpl类,
//为了下面的populateBean方法的属性注入做准备
if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
复制代码

代码 2:

允许后处理器修改合并的bean定义。

synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {//异常:Post-processing of merged bean definition failed}mbd.postProcessed = true;}}
复制代码

代码 3 :

即使被BeanFactoryAware等生命周期接口触发,也要尽快地缓存singletons 以便能够解析循环引用。

boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {if (logger.isDebugEnabled()) {logger.debug("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}addSingletonFactory(beanName, new ObjectFactory<Object>() {@Overridepublic Object getObject() throws BeansException {return getEarlyBeanReference(beanName, mbd, bean);}});
}
复制代码

代码 4:

这里是对bean的初始化的地方,一般情况下依赖注入就在这里发生;这个exposedObject变量保存的是在初始化处理完以后返回的作为依赖注入完成之后的bean。

// Initialize the bean instance.
Object exposedObject = bean;
try {populateBean(beanName, mbd, instanceWrapper);if (exposedObject != null) {exposedObject = initializeBean(beanName, exposedObject, mbd);}
}
catch (Throwable ex) {//抛出if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException)ex).getBeanName())) {throw (BeanCreationException) ex;}else {//异常:Initialization of bean failed}
}
复制代码

代码 5:

这里是注册bean

try {registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {//异常处理
}
//返回结果
return exposedObject;
复制代码

上面的5个代码段均是doCreateBean中的处理逻辑,有兴趣的小伙伴可以自行查阅源码。从上面的代码中我们依然没有得到具体创建的过程,因为在doCreateBean中又依赖:createBeanInstancepopulateBean两个方法。

createBeanInstance中生成了Bean所包含的java对象。来看是怎么生成的:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {// 确保bean类实际上已经解析过了,可以实例化Class<?> beanClass = resolveBeanClass(mbd, beanName);if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {//异常:Bean class isn't public, and non-public access not allowed:beanName}//1. 使用工厂方法来进行bean的实例化if (mbd.getFactoryMethodName() != null)  {return instantiateUsingFactoryMethod(beanName, mbd, args);}// 重新创建相同的bean时快捷方式...boolean resolved = false;boolean autowireNecessary = false;if (args == null) {synchronized (mbd.constructorArgumentLock) {if (mbd.resolvedConstructorOrFactoryMethod != null) {resolved = true;autowireNecessary = mbd.constructorArgumentsResolved;}}}if (resolved) {if (autowireNecessary) {return autowireConstructor(beanName, mbd, null, null);}else {return instantiateBean(beanName, mbd);}}// 2.需要确定构造函数...,使用构造函数进行bean实例化Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if (ctors != null ||mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {return autowireConstructor(beanName, mbd, ctors, args);}//3.没有特殊的处理:只需使用无参数构造函数。(默认构造函数)return instantiateBean(beanName, mbd);
}
复制代码

从上面这段代码可以看出,对象的生成有许多不同的方式,有通过工厂的,也有通过容器的autowire特性生成的。当然这些生成方式都是由相关的BeanDefinition来指定的。

Spring中配置Bean的方式我们常用的一种是通过xml文件来配置,还有就是通过注解的方式来配置

  • demo1
<bean id="user" class="com.glmapper.test.User"><property name="name" value="glmapper"></property>
</bean>
复制代码

这种方式,通过class提供的权限定名,spring就可以利用反射机制创建这个bean。

  • demo2
<bean id="user" class="com.glmapper.test.UserFactory" factory-method="getUser"><constructor-arg value="glmapper"></constructor-arg>
</bean>
复制代码

这种是利用静态工厂方法来创建的,提供的class并非是类的权限定名, 而是静态工厂的全类名;除此之外还需要指定获取bean的方法(此处是getUser)和参数(参数是glmapper)。

  • demo3
<bean id="userFactory" class="com.glmapper.test.UserInstanceFactory"><!--用一个集合来保存我当前的对象实例--><property name="map"><map><entry key="user1"><bean class="com.glmapper.test.User"><property name="name" value="glmapper1"></property>        </bean></entry>    <entry key="user2"><bean class="com.glmapper.test.User"><property name="name" value="glmapper2"></property>   </bean></entry></map>  </property></bean>//实例1<bean id="user1" factory-bean="userFactory" factory-method="getUserInstance"><constructor-arg value="user1"></constructor-arg>           </bean>
//实例2<bean id="user2" factory-bean="userFactory" factory-method="getUserInstance"><constructor-arg value="user2"></constructor-arg>           </bean
复制代码

这种方式和静态工厂的区别在于我们需要先实例化一个工厂对象,然后才能使用这个工厂对象来创建我们的bean。getUserInstance通过key值来获取我们已经实例化好的对象(当然方式有很多,此处以map来举个例子)。关于注解的和使用FactoryBean接口的这里就暂时不说,后期再聊

OK,继续来分钟,上面说到的是以工厂方法创建bean,具体的源码有点长,这里就不放了,大概思路就如上面所提到的那几种方式。接下来看下常见的使用instantiateBean方式(使用它的默认构造函数)来构建bean的代码:

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {try {Object beanInstance;final BeanFactory parent = this;//获取系统安全接口。//如果已经为当前应用程序建立了安全管理器,则返回该安全管理器; //否则,返回null。if (System.getSecurityManager() != null) {beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {@Overridepublic Object run() {return getInstantiationStrategy().instantiate(mbd, beanName, parent);}}, getAccessControlContext());}else {beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);}BeanWrapper bw = new BeanWrapperImpl(beanInstance);initBeanWrapper(bw);return bw;}catch (Throwable ex) {//异常:Instantiation of bean failed}
}
复制代码

可以看出,上面的创建都是通过:

getInstantiationStrategy().instantiate(mbd, beanName, parent);
复制代码

这样一段代码来完成的,是的,这里已经快接近真相了。从语义上来分析,先是获取了一种策略,然后利用当前获取的策略再去执行实例化。OK,我们看下getInstantiationStrategy()拿到的是什么:

//返回实例化策略用于创建bean实例。
protected InstantiationStrategy getInstantiationStrategy() {return this.instantiationStrategy;
}
//默认的实例化测试是使用CGLIB代理
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
复制代码

看到这里我们清楚了,默认构造函数的情况下,在spring中会使用Cglib来进行bean的实例化(关于cglib此处不再赘述)。我们看下CglibSubclassingInstantiationStrategy这个类的申明:

public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationStrategy
复制代码

它继承自SimpleInstantiationStrategy ,这个又是什么鬼呢?

SimpleInstantiationStrategy是Spring用来生成Bean对象的默认类,在这个类中提供了两种实例化java对象的方法,一种是基于java自身反射机制的BeanUtils,还有一种就是基于Cglib

如何创建的就不说了;到这里createBeanInstance就说完了(Bean已经创建了);但是仅仅是创建,spring还没有处理它们,比如说bean对象的属性,依赖关系等等。这些就是上面提到的另外一个方法populateBean;

这个方法其实就做了一件事:**使用bean定义中的属性值在给定的BeanWrapper中填充bean实例。**分段来看: 下面这段代码是先将BeanDefinition中设置的property值封装成PropertyValues,然后检测我们的BeanWrapper是否为Null,如果为null则抛出异常或者跳过当前空实例赋值阶段

//获取到BeanDefinition中设置的property值,封装成PropertyValues
PropertyValues pvs = mbd.getPropertyValues();
if (bw == null) {if (!pvs.isEmpty()) {//异常:Cannot apply property values to null instance}else {// Skip property population phase for null instance.return;}
}
复制代码

下面这段代码的意思是给任何InstantiationAwareBeanPostProcessors提供在设置属性之前修改bean状态的机会。

boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {continueWithPropertyPopulation = false;break;}}}
}if (!continueWithPropertyPopulation) {return;
}
复制代码

下面就是对具体注入方式的处理:

//处理autowire的注入;可以根据bean的名称和类型来注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs);// 则根据名称添加基于自动装配的属性值。if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);}// 根据类型添加基于自动装配的属性值。if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);}pvs = newPvs;
}
复制代码

两个判断条件,在满足的情况下做的处理分别是:

  • 在工厂将给定属性值应用到给定的bean后,对其进行后处理。 允许检查所有的依赖关系是否被满足,例如基于bean属性设置器上的“Required”注解。还允许替换要应用的属性值,通常通过创建基于原始PropertyValues的新MutablePropertyValues实例,添加或删除特定值。
  • 执行依赖性检查
//返回这个工厂是否拥有一个InstantiationAwareBeanPostProcessor
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
//返回依赖检查代码。
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);if (hasInstAwareBpps || needsDepCheck) {
//从给定的BeanWrapper中提取一组已过滤的PropertyDescriptors,
//不包括在被忽略的依赖性接口上定义的被忽略的依赖类型或属性(译注)。PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);if (hasInstAwareBpps) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvs == null) {return;}}}}if (needsDepCheck) {checkDependencies(beanName, mbd, filteredPds, pvs);}
}
复制代码

最后是对属性进行注入:

applyPropertyValues(beanName, mbd, bw, pvs);
复制代码

这个方法描述的是对属性进行解析然后注入的过程;先来分析下applyPropertyValues的申明:

protected void applyPropertyValues(String beanName
, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs)
复制代码
  • beanName bean名称
  • mbd 合并的bean definition
  • bw 包装目标对象的BeanWrapper
  • pvs 新的属性值

代码分段来看:

  • 参数验证
if (pvs == null || pvs.isEmpty()) {return;
}
复制代码
  • pvs参数处理
if (pvs instanceof MutablePropertyValues) {mpvs = (MutablePropertyValues) pvs;if (mpvs.isConverted()) {// 使用预先转换后的值。try {bw.setPropertyValues(mpvs);return;}catch (BeansException ex) {//异常:Error setting property values}}original = mpvs.getPropertyValueList();}else {original = Arrays.asList(pvs.getPropertyValues());}
复制代码
  • valueResolver来解析BeanDefinition
BeanDefinitionValueResolver valueResolver =
new BeanDefinitionValueResolver(this, beanName, mbd, converter);
复制代码
  • 为解析值创建一个副本,注入到bean中的是副本的数据
// Create a deep copy, resolving any references for values.
List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
复制代码
  • 遍历处理
boolean resolveNecessary = false;
for (PropertyValue pv : original) {//返回此持有者是否已经包含转换后的值(true),还是需要转换值(false)。if (pv.isConverted()) {deepCopy.add(pv);}   else {String propertyName = pv.getName();Object originalValue = pv.getValue();//看下面的注释resolveValueIfNecessaryObject resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);Object convertedValue = resolvedValue;boolean convertible = bw.isWritableProperty(propertyName) &&!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);if (convertible) {convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);}// 可能将转换的值存储在合并的bean定义中,以避免为每个创建的bean实例重新转换。if (resolvedValue == originalValue) {if (convertible) {pv.setConvertedValue(convertedValue);}deepCopy.add(pv);}else if (convertible && originalValue instanceof TypedStringValue &&!((TypedStringValue) originalValue).isDynamic() &&!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {pv.setConvertedValue(convertedValue);deepCopy.add(pv);}else {resolveNecessary = true;deepCopy.add(new PropertyValue(pv, convertedValue));}}
}
复制代码
  • resolveValueIfNecessary

    给定一个PropertyValue,返回一个value,必要时解析对工厂中其他bean的引用。value可以是:

    • 一个BeanDefinition,它导致创建一个相应的新的bean实例。 Singleton标志和这样的"inner beans"的名字被忽略:内部beans是匿名原型。
    • RuntimeBeanReference(必须解析)
    • ManagedList
    • ManagedSet
    • ManagedMap
    • 一个普通的对象或null,在这种情况下,它是孤立的。

下面这段代码时依赖注入发生的地方,其实际上是在BeanWrapperImpl中来完成。

try {bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {//异常:Error setting property values
}
复制代码

上面说到spring是通过BeanDefinitionValueResolver来解析BeanDefinition的,然后再注入到property中,关于这个过程在下一篇中来说。

欢迎关注微信公众号

Spring源码系列:依赖注入(二)createBean相关推荐

  1. 初学者都能看懂的 Spring 源码之依赖注入(DI)源码分析

    前言 在面试中,经常被问到 Spring 的 IOC 和 DI (依赖注入),很多人会觉得其实 IOC 就是 DI ,但是严格上来说这两个其实并不等价,因为 IOC 注重的是存,而依赖注入注重的是取, ...

  2. Spring源码系列(十二)Spring创建Bean的过程(二)

    1.写在前面 上篇博客主要Spring在创建Bean的时候,第一次调用的Bean的后置处理器的过程,同时笔者也打算将整个Spring创建的Bean的过程,通过这个系列,将Bean的创建过程给讲清楚,废 ...

  3. 【spring源码系列-05】refresh中prepareRefresh方法的执行流程

    Spring源码系列整体栏目 内容 链接地址 [一]spring源码整体概述 https://blog.csdn.net/zhenghuishengq/article/details/13094088 ...

  4. Ioc容器beanDefinition-Spring 源码系列(1)

    Ioc容器beanDefinition-Spring 源码系列(1) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器 ...

  5. Spring源码系列- Spring Beans - 核心类的基本介绍

    Spring源码系列- Spring Beans - 核心类的基本介绍 读过上一篇文章的读者应该都能对Spring的体系结构有一个大致的了解,在结尾处,我也说过会从spring-beans包开始分析, ...

  6. Spring源码系列:BeanDefinition载入(下)

    在Spring源码系列:BeanDefinition载入(上)中已经大概捋了一下解析过程,本篇将记录一下bean的注册过程. bean的注册就是DefaultListableBeanFactory中r ...

  7. 闷棍暴打面试官 Spring源码系列: (一) Spring 如何解决循环依赖

    前言 初夏时节, 时间: AM 7.30分左右, 空无一人的健身房里,一个硕大的身体在跑步机上扭动着, 不一会头上便挥汗如雨, 他嘴上还不时嘀咕着 "循环依赖,单例模式,Bean的定位加载注 ...

  8. Spring源码剖析 循环注入

    版权声明:本文为CSDN博主「shadow?s」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog.csdn.net/java_ly ...

  9. spring源码系列一--BeanDefinition

    如果说java是由对象组成,那么spring-framework框架可以说是由BeanDefinition所构成.BeanDefinitiion其实是spring中的顶级接口,我们在阅读源码之前必须要 ...

最新文章

  1. 写了一个PPT,用于公司内部培训
  2. oracle中通过游标实现查询
  3. linux的基础知识——shell基础
  4. P1255 数楼梯 方法二(python3实现)
  5. java gpu hash_比特币 GPU 挖矿 Sha256 Hash实现(OpenCL)
  6. [转载] python3 闭包
  7. DDD领域驱动设计 思维导图
  8. 4600万台销量!树莓派炼成之路
  9. python爬虫免登录_爬虫使用cookie免登陆
  10. 网络:网络地址到虚拟地址的映射ARP
  11. hdu 6609
  12. c语言实现utf-8编码解码器
  13. Log4j2配置SMTP邮件实现邮件发送
  14. Pycharm 许可证过期解决
  15. WebGL简易教程(五):图形变换(模型、视图、投影变换)
  16. 计算机网络常见笔试面试题(一)
  17. CSS 变形(CSS3) transform
  18. Python软件编程等级考试二级——20210314
  19. 斗鱼直播行业名列前茅 泛娱乐布局成效凸显
  20. 什么是熵增?如何对抗熵增?

热门文章

  1. java纪元时间_Java实现纪元秒和本地日期时间互换的方法【经典实例】
  2. HDU 4747 Mex【线段树上二分+扫描线】
  3. 初来乍到,请多指教。
  4. JavaScript 中的函数介绍
  5. JQuery版评分控件
  6. div+css 简单导航
  7. SpringMVC自学日志05(结果跳转方式,数据处理 ,乱码问题)
  8. MySQL客户端mysql常用命令
  9. Ranger-Sqoop2插件实现详解
  10. JAVA设计模式 - 建造者模式