Spring BeanFacoty doCreateBean方法分析
上一篇,我们分析到了doCreateBean,现在继续:
先看看时序图
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { //*************************5.4.1 instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null); // Allow post-processors to modify the merged bean definition. //*************************5.4.2 synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); mbd.postProcessed = true; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. //*************************5.4.3 处理循环依赖的问题 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() { public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } }); } // Initialize the bean instance. Object exposedObject = bean; try { //*************************5.4.4 将mdb中的值放到instanceWrapper中 populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) { //*************************5.4.5 正儿八经的初始化 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) { Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<String>(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 { //*************************5.4.6 注册销毁方法 registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }
在5.4.1处
首先判断是否有factory-method属性
即:
<bean id="bar" class="...StaticBarInterfaceFactory" factory-method="getInstance"/>
如果有就直接通过工厂方法生产之。 参见 拙作spring中工厂方法 http://blog.csdn.net/dlf123321/article/details/47856937#t6
如果没有有默认的构造方法,且bean中包含constructor-arg
<bean id="newsBean3" class="com.luhy.spring.hello.FXNewsBean" scope="singleton"> <constructor-arg> <value>This is a configurable message</value> </constructor-arg> </bean>
就调用默认的含参构造方法。
否则调用instantiateBean
AbstractAutowireCapableBeanFactory.java protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { try { Object beanInstance; final BeanFactory parent = this; if (System.getSecurityManager() != null) { beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() { public 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) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); } }
我们在AbstractAutowireCapableBeanFactory里可以看到
/** Strategy for creating bean instances */ private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy(); getInstantiationStrategy()返回的是InstantiationStrategy接口的实现类,默认是CglibSubclassingInstantiationStrategy。
通过cglib生成实例对象。
至5.4.1,BeanWrapper的生成基本清晰了。
5.4.2处是允许其他修改beanDefinition,这主要是允许其他组件提供xml不能提供的信息。如使用Annotation增强Bean定义等。这通过类ergedBeanDefinitionPostProcessor来完成,如果容器中提供了此类实现,则会调用进行bean增强。如CommonAnnotationBeanPostProcessor类,会在bean定义中追加如 @Resource之类的bean property引用信息。此代码如下所示:
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class beanType, String beanName) throws BeansException { try { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof MergedBeanDefinitionPostProcessor) { MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp; bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName); } } } catch (Exception ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing failed of bean type [" + beanType + "] failed", ex); } }
在5.4.3处,关于循环依赖问题,可以参考 http://www.iflym.com/index.php/code/201208280001.html
在5.4.4处populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw)
说实话,我第一回看到这方法的时候,populate,流行的?流行的bean? 呵呵,见笑了。
在populate里面
/** * Populate the bean instance in the given BeanWrapper with the property values * from the bean definition. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @param bw BeanWrapper with bean instance */ protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) { PropertyValues pvs = mbd.getPropertyValues(); if (bw == null) { if (!pvs.isEmpty()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { // Skip property population phase for null instance. return; } } // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. //*******************5.4.4.1 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; } //*******************5.4.4.2 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); //*******************5.4.4.3 if (hasInstAwareBpps || needsDepCheck) { PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw); 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); } } //*******************5.4.4.4 applyPropertyValues(beanName, mbd, bw, pvs); }
好长呀,慢慢来,这里大概可以分为4部分
首先5.4.4.1
如果所要获取的bean实现了InstantiationAwareBeanPostProcessor接口,就调用其postProcessAfterInstantiation方法。
<span style="white-space:pre"> </span>// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. 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; }
多说几句,postProcessAfterInstantiation的返回值是一个boolean,如果返回值是false,就说明已经属性处理已经结束了。后面的代码就不运行了。
接着5.4.4.2
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; }
不需要解释了吧,就是处理autowire标签。
再然后5.4.4.3
给InstantiationAwareBeanPostProcessor机会以处理属性信息,比如在xml中描述了Annotation定义,使用了<context:annotation-config/>,那么就会使用类CommonAnnotationBeanPostProcessor进行注解类属性注入。如下代码所示:
if (hasInstAwareBpps || needsDepCheck) { PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw); 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); } }
我们看下面的解释:
最后5.4.4.4
applyPropertyValues(beanName, mbd, bw, pvs)干的事情就是填充值。
这里都干了什么事情,我举个例子。
<bean id="newsBean2" class="com.luhy.spring.hello.FXNewsBean" scope="prototype"> <property name="p"> <value>dlf</value> </property> </bean>
com.luhy.spring.hello.FXNewsBean中p这个属性是一个Person。
如何将字符串"dlf"(在xml中,所有的信息不都是字符么)转换为person呢?
我们需要下面这个类:
public class PersonEditor extends PropertyEditorSupport { @Override public void setAsText(String text) throws IllegalArgumentException { Person p = new Person(); p.setName(text); System.out.println("setAsTest"); setValue(p); } }
那么什么时候调用这个PersonEditor呢?就在5.4.5.4的applyPropertyValues里。
当然,这里我只是举个例子。这里还包括集合类型的转换,基本类型的转换等等。
关于类型转换参见 http://blog.csdn.net/dlf123321/article/details/47905533#t3
关于5.4.5
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { invokeAwareMethods(beanName, bean); return null; } }, getAccessControlContext()); } else { //处理XXAware接口的实现 //beanFactoryAware这这个处理 invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { //处理postProcessBeforeInitialization <span style="white-space:pre"> </span>//在这里处理ApplicationContextAware(使用ApplicationContextAwareProcessor) wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { //这里面调用了 InitializingBean的afterPropertiesSet //同时还有init-method指定的方法 invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { //postProcessAfterInitialization方法 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
总结一下初始化顺序
XXAware接口的实现->postProcessBeforeInitialization->InitializingBean的afterPropertiesSet-> custom Init方法->postProcessAfterInitialization
OK.这就是bean初始化的顺序啦!
5.4.6注册销毁方法
至此,获取对象完毕。
参考资料
http://blog.csdn.net/dlf123321/article/details/47856937#t6 spring中工厂方法
http://www.iflym.com/index.php/code/201208280001.html 循环引用
http://www.iflym.com/index.php/code/201208290001.html Spring中获取一个bean的流程-1
http://michael-softtech.iteye.com/blog/816469 spring源码分析之——spring bean的获取
http://blog.csdn.net/dlf123321/article/details/47905533#t3 关于类型转换
http://blog.csdn.net/zhoudaxia/article/details/36247883#t5 关于类型转换
Spring BeanFacoty doCreateBean方法分析的更多相关文章
- spring的finishBeanFactoryInitialization方法分析
spring源码版本5.0.5 概述 该方法会实例化所有剩余的非懒加载单例 bean.除了一些内部的 bean.实现了 BeanFactoryPostProcessor 接口的 bean.实现了 Be ...
- Spring Ioc源码分析系列--容器实例化Bean的四种方法
Spring Ioc源码分析系列--实例化Bean的几种方法 前言 前面的文章Spring Ioc源码分析系列--Bean实例化过程(二)在讲解到bean真正通过那些方式实例化出来的时候,并没有继续分 ...
- Spring IOC 源码分析
Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文 ...
- Spring AOP源码分析--代理方式的选择
能坚持别人不能坚持的,才能拥有别人未曾拥有的.关注编程大道公众号,让我们一同坚持心中所想,一起成长!! 年前写了一个面试突击系列的文章,目前只有redis相关的.在这个系列里,我整理了一些面试题与大家 ...
- Spring源码--debug分析循环依赖--构造器注入
目的:源码调试构造器注入,看看是怎么报错的. spring:5.2.3 jdk:1.8 一.准备 首先准备两个循环依赖的类:userService和roleServic <bean id=&qu ...
- 5.2 Spring5源码--Spring AOP源码分析二
目标: 1. 什么是AOP, 什么是AspectJ 2. 什么是Spring AOP 3. Spring AOP注解版实现原理 4. Spring AOP切面原理解析 一. 认识AOP及其使用 详见博 ...
- 干货分享之spring框架源码分析02-(对象创建or生命周期)
记录并分享一下本人学习spring源码的过程,有什么问题或者补充会持续更新.欢迎大家指正! 环境: spring5.X + idea 之前分析了Spring读取xml文件的所有信息封装成beanDef ...
- Spring Ioc源码分析系列--Bean实例化过程(一)
Spring Ioc源码分析系列--Bean实例化过程(一) 前言 上一篇文章Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理已经完成了对 ...
- Spring Ioc源码分析系列--Bean实例化过程(二)
Spring Ioc源码分析系列--Bean实例化过程(二) 前言 上篇文章Spring Ioc源码分析系列--Bean实例化过程(一)简单分析了getBean()方法,还记得分析了什么吗?不记得了才 ...
随机推荐
- Arrays的二分查找
二分查找也称为折半查找,是对有序元素查找的一种算法,在查找的过程中,不断的将搜索长度减半,因此效率不错.Java的JDK提供了二分法查找的算法,使用的方法是Arrays.binarySearch(). ...
- 给大家安利一个学习angular2的视频网站
本文地址:http://blog.csdn.net/sushengmiyan 本文作者:苏生米沿 视频地址: https://egghead.io/courses/angular-2-fundamen ...
- valgrind检测内存泄漏
Valgrind 使用 用法:valgrind [options] prog-and-args [options]: 常用选项,适用于所有Valgrind工具 -tool=<name>最常 ...
- Android 5.0新控件——FloatingActionButton(悬浮按钮)
Android 5.0新控件--FloatingActionButton(悬浮按钮) FloatingActionButton是5.0以后的新控件,一个悬浮按钮,之所以叫做悬浮按钮,主要是因为自带阴影 ...
- AsyncTask函数化的封装,AsyncTask函数式的调用
AsyncTask在本专栏已经做过详细的解析,但是AsyncTask函数式的调用这个概念对大多数人来说比较陌生.其实本质就是自己封装AsyncTask,让暴露的方法,看不到一点AsyncTask的身影 ...
- Linux下一次数据仓库进行迁移记录
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52768613 前言:数据库每天的 ...
- Android事件分发传递回传机制详解
转载本专栏每一篇博客请注明转载出处地址,尊重原创.此博客转载链接地址:点击打开链接 http://blog.csdn.net/qq_32059827/article/details/5257701 ...
- Android App之间通过Intent交互
Android 最重要的功能之一是应用能够基于它要执行的"操作"向另一个应用发送用户. 例如,如果您的应用有您要在地图上显示的公司地址,您无需在显示地图的应用中构建 Activit ...
- Hibernate实体映射文件多对多等关系简单应用技巧
认真开完以后,就能很简单的写出各种关系了 第一步,写注释: <!--xx属性,本类与Yy(类)的多对一 --> <!--xx属性,本类与Yy(类)的一对多 --> <!- ...
- Java基本语法-----java函数
函数的概述 发现不断进行加法运算,为了提高代码的复用性,就把该功能独立封装成一段独立的小程序,当下次需要执行加法运算的时候,就可以直接调用这个段小程序即可,那么这种封装形形式的具体表现形式则称作函数. ...