转自: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. jenkins+maven+svn构建项目,及远程部署war包到tomcat上

    要使用jenkins构建项目,当然要使用jenkins了,我使用的war版本的jenkins jenkins的官网 http://jenkins-ci.org/ 点击latest下载,但是可能因为天朝 ...

  2. javaweb获取项目路径的方法

    在jsp和class文件中调用的相对路径不同. 在jsp里,根目录是WebRoot 在class文件中,根目录是WebRoot/WEB-INF/classes 当然你也可以用System.getPro ...

  3. Scala_针对集合的操作

    针对集合的操作 遍历操作 列表的遍历 scala> val list = List(1,2,3,4,5,6) list: List[Int] = List(1, 2, 3, 4, 5, 6) s ...

  4. FastReport调整字体

  5. mysql数据导入导出方法总结

    MySQL数据备份还原方式总结: 一.将数据导入到指定的数据库 第一种导入方式: (linux下和Windows 下语法是一样的,只是路径的书写方式不同而已) 1.创建一个空数据库 2.进入MySQL ...

  6. 深度学习主机环境配置: Ubuntu16.04+GeForce GTX 1080+TensorFlow

    接上文<深度学习主机环境配置: Ubuntu16.04+Nvidia GTX 1080+CUDA8.0>,我们继续来安装 TensorFlow,使其支持GeForce GTX 1080显卡 ...

  7. UWP 多语言的三个概念

    首先了解一下 RFC4646 和 BCP-47 是什么东西: RFC4646 The name is a combination of an ISO 639 two-letter lowercase ...

  8. UWP 使用Windows Community Toolkit 的OneDrive service上传下载文件

    上一年年底写过两篇文章 UWP 使用OneDrive云存储2.x api(一)[全网首发] UWP 使用OneDrive云存储2.x api(二)[全网首发] 没想到半年之后,VS编译提示方法已经过时 ...

  9. fatal: LF would be replaced by CRLF in index.html

    进入项目目录,在.git文件夹下打开config配置文件,添加上下面两句话: autocrlf = false safecrlf = false 即可

  10. Swift5 语言参考(九) 泛型和参数

    本章介绍泛型类型,函数和初始值设定项的参数和参数.声明泛型类型,函数,下标或初始化程序时,可以指定泛型类型,函数或初始化程序可以使用的类型参数.当创建泛型类型的实例或调用泛型函数或初始化程序时,这些类 ...