转自:http://songzi0206.iteye.com/blog/1430239

当 BeanDefinition 注册完毕以后, Spring Bean 工厂就可以随时根据需要进行实例化了。对于XmlBeanFactory 来说,实例化默认是延迟进行的,也就是说在 getBean 的时候才会;而对于 ApplicationContext来说,实例化会在容器启动后通过 AbstractApplicationContext 中 reflash 方法自动进行,主要经过方法链:reflesh()   à finishBeanFactoryInitialization (factory) à DefaultListableBeanFactory.preInstantiateSingletons (), 在这里会根据注册的 BeanDefinition 信息依此调用 getBean(beanName) 。而真正实例化的逻辑和 BeanFactory 是“殊途同归”的,所有有关 Bean 实例化都可以从 getBean(beanName) 入手。

AbstractBeanFactory 有四个 getBean 的重载方法,不管调用哪个方法最终都是会调用另一个 doGetBean 方法:

  1. public Object getBean(String name) throws BeansException {
  2. return getBean(name, null, null);
  3. }
  4. public Object getBean(String name, Class requiredType) throws BeansException {
  5. return getBean(name, requiredType, null);
  6. }
  7. public Object getBean(String name, Object[] args) throws BeansException {
  8. return getBean(name, null, args);
  9. }
  10. /**
  11. * Return an instance, which may be shared or independent, of the specified bean.
  12. * @param name the name of the bean to retrieve
  13. * @param requiredType the required type of the bean to retrieve
  14. * @param args arguments to use if creating a prototype using explicit arguments to a
  15. * static factory method. It is invalid to use a non-null args value in any other case.
  16. * @return an instance of the bean
  17. * @throws BeansException if the bean could not be created
  18. */
  19. public Object getBean(String name, Class requiredType, Object[] args) throws BeansException {
  20. return doGetBean(name, requiredType, args, false);
  21. }

doGetBean方法比较长一点,见下面注释:

  1. protected Object doGetBean(
  2. final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)
  3. throws BeansException {
  4. //bean name处理,去除FactoryBean前缀等
  5. final String beanName = transformedBeanName(name);
  6. Object bean = null;
  7. //先从singleton缓存中查看是否已经实例化过该Bean,根据是否有缓存分为两个分支分别处理
  8. Object sharedInstance = getSingleton(beanName);
  9. if (sharedInstance != null && args == null) {
  10. // 分支一,若缓存中获取到了并且该BeanDefinition信息表明该bean是singleton的,直接将获取到的缓存Bean
  11. //(有可能是半成品)交给getObjectForBeanInstance处理
  12. /*.........省略logger部分代码............*/
  13. //调用getObjectForBeanInstance处理
  14. bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
  15. }else {
  16. // 分之二:没有缓存,则需要从头实例化该bean
  17. // We're assumably within a circular reference.
  18. if (isPrototypeCurrentlyInCreation(beanName)) {
  19. throw new BeanCurrentlyInCreationException(beanName);}
  20. // 检查BeanDefinition是否在当前工厂或父工厂
  21. BeanFactory parentBeanFactory = getParentBeanFactory();
  22. if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
  23. // Not found -> check parent.
  24. String nameToLookup = originalBeanName(name);
  25. if (args != null) {
  26. // 父工厂getBean
  27. return parentBeanFactory.getBean(nameToLookup, args);
  28. }
  29. else {
  30. // No args -> delegate to standard getBean method.
  31. return parentBeanFactory.getBean(nameToLookup, requiredType);
  32. }
  33. }
  34. //将bean加入“正在创建”的集合,完成后会remove,对应afterSingletonCreation/afterPrototypeCreation方法
  35. if (!typeCheckOnly) {
  36. markBeanAsCreated(beanName);
  37. }
  38. final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
  39. checkMergedBeanDefinition(mbd, beanName, args);
  40. // 解决依赖关系,将依赖的bean提前实例化
  41. String[] dependsOn = mbd.getDependsOn();
  42. if (dependsOn != null) {
  43. for (int i = 0; i < dependsOn.length; i++) {
  44. String dependsOnBean = dependsOn[i];
  45. getBean(dependsOnBean);
  46. registerDependentBean(dependsOnBean, beanName);
  47. }
  48. }
  49. // 这里又需要根据bean的类型分为三种情况:singleton、prototype、request/session
  50. if (mbd.isSingleton()) {
  51. //通过自定义ObjectFactory实例化Bean,此结果可能是半成品(是FactoryBean等)
  52. sharedInstance = getSingleton(beanName, new ObjectFactory() {
  53. public Object getObject() throws BeansException {
  54. try {
  55. //真正实例化装配的逻辑在createBean方法中
  56. return createBean(beanName, mbd, args);
  57. }
  58. catch (BeansException ex) {
  59. // Explicitly remove instance from singleton cache: It might have been put there
  60. // eagerly by the creation process, to allow for circular reference resolution.
  61. // Also remove any beans that received a temporary reference to the bean.
  62. destroySingleton(beanName);
  63. throw ex;
  64. }
  65. }
  66. });
  67. //上一步半成品的Bean交给getObjectForBeanInstance方法处理
  68. bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
  69. }
  70. else if (mbd.isPrototype()) {
  71. // It's a prototype -> create a new instance.
  72. Object prototypeInstance = null;
  73. try {
  74. beforePrototypeCreation(beanName);
  75. //真正实例化装配的逻辑在createBean方法中
  76. prototypeInstance = createBean(beanName, mbd, args);
  77. }
  78. finally {
  79. afterPrototypeCreation(beanName);
  80. }
  81. //上一步半成品的Bean交给getObjectForBeanInstance方法处理
  82. bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
  83. }
  84. else {
  85. //request、session 的bean
  86. String scopeName = mbd.getScope();
  87. final Scope scope = (Scope) this.scopes.get(scopeName);
  88. if (scope == null) {
  89. throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
  90. }
  91. try {
  92. Object scopedInstance = scope.get(beanName, new ObjectFactory() {
  93. public Object getObject() throws BeansException {
  94. beforePrototypeCreation(beanName);
  95. try {
  96. //真正实例化装配的逻辑在createBean方法中
  97. return createBean(beanName, mbd, args);
  98. }
  99. finally {
  100. afterPrototypeCreation(beanName);
  101. }
  102. }
  103. });
  104. //上一步半成品的Bean交给getObjectForBeanInstance方法处理
  105. bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
  106. }
  107. catch (IllegalStateException ex) {
  108. throw new BeanCreationException(beanName,
  109. "Scope '" + scopeName + "' is not active for the current thread; " +
  110. "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
  111. ex);
  112. }
  113. }
  114. }
  115. // Check if required type matches the type of the actual bean instance.
  116. if (requiredType != null && bean != null &&
  117. !requiredType.isAssignableFrom(bean.getClass())) {
  118. throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
  119. }
  120. return bean;
  121. }

通过注释,可以整理出较清晰的逻辑: 检查Bean缓存,已经有缓存的Bean对象(有可能是半成品)则交给getObjectForBeanInstance方法处理;否则先根据Bean的生命周期类型分别实例化,每种情况大致都分两步,第一步都交给createBean方法生产一个半成品的bean对象,然后同样是将半成品的bean交给getObjectForBeanInstance方法处理。所以关键的逻辑就在这两个方法了,下面以singleton为例看看这两个方法,具体代码:

  1. sharedInstance = getSingleton(beanName, new ObjectFactory() {
  2. public Object getObject() throws BeansException {
  3. try {
  4. return createBean(beanName, mbd, args);
  5. }
  6. catch (BeansException ex) {
  7. // Explicitly remove instance from singleton cache: It might have been put there
  8. // eagerly by the creation process, to allow for circular reference resolution.
  9. // Also remove any beans that received a temporary reference to the bean.
  10. destroySingleton(beanName);
  11. throw ex;
  12. }
  13. }
  14. });
  15. bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

getSingleton方法做的工作主要是实例化bean之前和之后回调beforeSingletonCreation/afterSingletonCreation、实例化bean、以及将bean对象缓存起来,具体实例化bean是通过回调匿名对象ObjectFactory的getObject方法实现的,从代码中明显看到主要是createBean方法。这里要特别注意下,缓存的bean对象是createBean生产的,这个方法生产的bean只是“半成品”,有可能是个factoryBean,真正返回给客户端使用的bean还必须进行下一步getObjectBeanInstance处理。所以缓存的bean对象可以认为是“半成品”,这就和前文代码中的注释相呼应(缓存中若取到了bean,必须进行getObjectBeanInstance处理)。

对createBean方法实际上在“Spring IOC之BeanFactory”中已经有过分析,所以流程就不再简单重复,直接按步骤:

1.  resolveBeanClass(mbd, beanName);

2.  mbd.prepareMethodOverrides();//Spring IOC之BeanFactory已有解释,不重复

3.  Object bean = resolveBeforeInstantiation(beanName, mbd);

解释下,这里主要对于一些代理的bean做处理,我们平常经常会配置一些AOP模块,对于需要aop增强的bean实际上都会经过spring代理织入,而这些bean的代理逻辑应该就在这里处理了,具体看看这部分的代码:

  1. /**
  2. * Apply before-instantiation post-processors, resolving whether there is a
  3. * before-instantiation shortcut for the specified bean.
  4. * @param beanName the name of the bean
  5. * @param mbd the bean definition for the bean
  6. * @return the shortcut-determined bean instance, or <code>null</code> if none
  7. */
  8. protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
  9. Object bean = null;
  10. if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
  11. // Make sure bean class is actually resolved at this point.
  12. if (mbd.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  13. bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName);
  14. if (bean != null) {
  15. bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
  16. }
  17. }
  18. mbd.beforeInstantiationResolved = Boolean.valueOf(bean != null);
  19. }
  20. return bean;
  21. }
  22. /**
  23. * Apply InstantiationAwareBeanPostProcessors to the specified bean definition
  24. * (by class and name), invoking their <code>postProcessBeforeInstantiation</code> methods.
  25. * <p>Any returned object will be used as the bean instead of actually instantiating
  26. * the target bean. A <code>null</code> return value from the post-processor will
  27. * result in the target bean being instantiated.
  28. * @param beanClass the class of the bean to be instantiated
  29. * @param beanName the name of the bean
  30. * @return the bean object to use instead of a default instance of the target bean, or <code>null</code>
  31. * @throws BeansException if any post-processing failed
  32. * @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
  33. */
  34. protected Object applyBeanPostProcessorsBeforeInstantiation(Class beanClass, String beanName)
  35. throws BeansException {
  36. for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {
  37. BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
  38. if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) {
  39. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor;
  40. Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
  41. if (result != null) {
  42. return result;
  43. }
  44. }
  45. }
  46. return null;
  47. }
  48. //AbstractAutoProxyCreator
  49. public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
  50. Object cacheKey = getCacheKey(beanClass, beanName);
  51. if (!this.targetSourcedBeans.contains(cacheKey)) {
  52. if (this.advisedBeans.contains(cacheKey) || this.nonAdvisedBeans.contains(cacheKey)) {
  53. return null;
  54. }
  55. if (isInfrastructureClass(beanClass, beanName) || shouldSkip(beanClass, beanName)) {
  56. this.nonAdvisedBeans.add(cacheKey);
  57. return null;
  58. }
  59. }
  60. // Create proxy here if we have a custom TargetSource.
  61. // Suppresses unnecessary default instantiation of the target bean:
  62. // The TargetSource will handle target instances in a custom fashion.
  63. TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
  64. if (targetSource != null) {
  65. this.targetSourcedBeans.add(beanName);
  66. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
  67. Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
  68. this.proxyTypes.put(cacheKey, proxy.getClass());
  69. return proxy;
  70. }
  71. return null;
  72. }

对于AutoProxy部分代码要放到spring aop部分中去写了,这里只要明白如果是代理bean在postProcessBeforeInstantiation阶段会返回一个proxy,这时候bean已经算是实例化好了,再调用applyBeanPostProcessorsAfterInitialization即BeanPostProcessor.postProcessAfterInitialization回调进行属性的设置。最后的结果就可以返回bean对象了,只是一个Proxy Bean Object.

4.  Object beanInstance = doCreateBean(beanName, mbd, args);//如果是代理bean就不会走到这一步

解释下:对于非代理的bean,基本上实例化的逻辑就在doCreateBean这个方法了,这个方法在“Spring IOC之BeanFactory”中已经有过分析,所以不重复解释了,贴一个bean生命周期的流程图做为createBean方法的结尾:

上图不是我所画,来源于spring IOC容器介绍。

半成品出来之后还需要调用getObjectForBeanInstance进一步处理,这个方法:

  1. protected Object getObjectForBeanInstance(
  2. Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
  3. // Don't let calling code try to dereference the factory if the bean isn't a factory.
  4. if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
  5. throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
  6. }
  7. // Now we have the bean instance, which may be a normal bean or a FactoryBean.
  8. // If it's a FactoryBean, we use it to create a bean instance, unless the
  9. // caller actually wants a reference to the factory.
  10. if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
  11. return beanInstance;
  12. }
  13. Object object = null;
  14. if (mbd == null) {
  15. object = getCachedObjectForFactoryBean(beanName);
  16. }
  17. if (object == null) {
  18. // Return bean instance from factory.
  19. FactoryBean factory = (FactoryBean) beanInstance;
  20. // Caches object obtained from FactoryBean if it is a singleton.
  21. if (mbd == null && containsBeanDefinition(beanName)) {
  22. mbd = getMergedLocalBeanDefinition(beanName);
  23. }
  24. boolean synthetic = (mbd != null && mbd.isSynthetic());
  25. object = getObjectFromFactoryBean(factory, beanName, !synthetic);
  26. }
  27. return object;
  28. }

开始部分是逻辑检查,是否是FactoryBean,后面是从factoryBean中获取实际的Bean。获取bean也是先检查缓存,没有缓存再getObjectFromFactoryBean获取,详细再doGetObjectFromFactoryBean方法中,最后将获取的bean缓存起来。代码就不贴了。

BeanDefinition到Bean的更多相关文章

  1. (spring-第6回【IoC基础篇】)BeanDefinition——实例化Bean之前的第一大利器。

    上节讲了Bean实例化的内部机制,这里再复述一遍: ResourceLoader从系统中加载XML配置信息,并由Resource来表示. BeanDefinitionReader从Resource中读 ...

  2. spring源码分析系列2:Bean与BeanDefinition关系

    接口表示一种能力,实现了一个接口,即拥有一种能力. BeanDefinition与Bean的关系, 就好比类与对象的关系. 类在spring的数据结构就是BeanDefinition.根据BeanDe ...

  3. Spring工厂方式创建Bean实例

    创建Bean实例的方式: 1) 通过构造器(有参或无参) 方式: <bean id="" class=""/> 2) 通过静态工厂方法 方式: &l ...

  4. SpringMVC 源码深度解析&lt;context:component-scan&gt;(扫描和注冊的注解Bean)

    我们在SpringMVC开发项目中,有的用注解和XML配置Bean,这两种都各有自己的优势,数据源配置比較经经常使用XML配置.控制层依赖的service比較经经常使用注解等(在部署时比較不会改变的) ...

  5. 4.0 spring-注册解析的Bean

    1.0 registerBeanDefinition 对于配置文件,解析也解析完了,装饰也装饰完了,对于得到的BeanDefinition已经可以满足后续的使用了,唯一剩下的工作就是注册了, 也就是: ...

  6. 【spring源代码分析】--Bean的解析与注冊

    接着上一节继续分析,DefaultBeanDefinitionDocumentReader的parseBeanDefinitions方法: protected void parseBeanDefini ...

  7. Spring多种加载Bean方式简析

    1 定义bean的方式 常见的定义Bean的方式有: 通过xml的方式,例如: <bean id="dictionaryRelMap" class="java.ut ...

  8. Spring读书笔记——bean解析

    前情回顾 上篇<Spring读书笔记--bean加载>我们从代码角度介绍了有哪些类负责解析XML文件,又是如何一步步从XML格式脱变成我们熟悉的bean的,直到DefaultBeanDef ...

  9. 【Spring源码分析】Bean加载流程概览

    代码入口 之前写文章都会啰啰嗦嗦一大堆再开始,进入[Spring源码分析]这个板块就直接切入正题了. 很多朋友可能想看Spring源码,但是不知道应当如何入手去看,这个可以理解:Java开发者通常从事 ...

随机推荐

  1. 第一次Java实验

      模仿JavaAppArguments.java实例,编写一个程序,此程序从命令行接受多个数字,求和之后输出. 1.设计思路:命令行参数都是字符串,必须将其转化成数字才能相加,定义一个数组接收字符串 ...

  2. 《计算机科学基础》学习笔记_Part 1 Computer and Data

    Technorati Tags: 计算机科学基础,读书笔记 Chapter 1. Introduction Ø  计算机:黑盒,Output Data=f(Input Data, Program) Ø ...

  3. csdn上讲一个实时计算架构比较清晰的一篇文章

    https://blog.csdn.net/ymh198816/article/details/51998085

  4. hdu 4961 数论?

    http://acm.hdu.edu.cn/showproblem.php?pid=4961 给定ai数组; 构造bi, k=max(j | 0<j<i,a j%ai=0), bi=ak; ...

  5. 分形之花篮(Flower Basket)

    这一篇展示的图形与上一篇文章分形之皇冠(Crown)很相似. 核心代码: static void FractalFlowerBasket(const Vector3& vStart, cons ...

  6. 转MySQL遇到的语法差异及解决方案

    最近公司项目需要从SQL Server转到MySQL, 在转的过程中遇到两者语法之间的一些差异,在网上找了解决方案后,特记录在此.由于解决方案可能有很多种,我只记录了自己使用过的,仅作参考. 1. 拼 ...

  7. 探索基于.NET下实现一句话木马之asmx篇

    0x01 前言 上篇介绍了一般处理程序(ashx)的工作原理以及实现一句话木马的过程,今天接着介绍Web Service程序 (asmx)下的工作原理和如何实现一句话木马,当然介绍之前笔者找到了一款a ...

  8. ionic 2.x 3.x项目结构解析

    myApp │ config.xml //项目配置文件,包名.名称.minSdkVersion等都在此处配置 │ ionic.config.json │ package.json //项目依赖文件列表 ...

  9. 全球第一开源ERP Odoo操作手册 数据库简介

    1.3 数据库简介 每一个独立核算的企业都有一套相互关联的账簿体系, 把这一套完整的账簿体系建立在计算机系统中就称为一个数据库. 一般一个企业只用一个数据库. 如果企业有几个下属的独立核算的实体,也可 ...

  10. Angular2入门体验

    好的工具往往使得开发应用更快更简单,而不是任何模块都手动开发.angualr cli就是一个支持 创建工程,添加文件,对各种任务如测试.打包.部署等迭代. 本文的目的就是基于TypeScript开发构 ...