转自: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. cocos 2dx 通过循环实现界面图形的摆放

    首先创建一个一维数组 this.starSprites = new Array(); 然后知道星星的间距和坐标后通过如下代码实现位置的摆放 for(var i = 0; i < 6; i++){ ...

  2. poj 3321 单点更新 区间求和

    Apple Tree Time Limit: 2000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Java c ...

  3. 11i - 12 Gather Schema Statistics fails with Ora-20001 errors after 11G database Upgrade (文档 ID 781813.1)

    11i - 12 Gather Schema Statistics fails with Ora-20001 errors after 11G database Upgrade (文档 ID 7818 ...

  4. [杂谈] 一个关于 as 的小测试

    代码如下:   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 procedure TForm1.Button1Click(Sender: TObject); va ...

  5. Ubuntu 修改环境变量

    按变量的生存周期来划分,Linux变量可分为两类,它们的修改方法如下:(1)永久的:需要修改配置文件,变量永久生效. 常见的配置文件包括: (1-1)/etc/profile:对所有用户生效:此文件为 ...

  6. Android常用库和插件

    下拉刷新 PullLoadMoreRecyclerView 实现RecyclerView下拉刷新和上拉加载更多以及RecyclerView线性.网格.瀑布流效果演示 https://github.co ...

  7. python做数据分析pandas库介绍之DataFrame基本操作

    怎样删除list中空字符? 最简单的方法:new_list = [ x for x in li if x != '' ] 这一部分主要学习pandas中基于前面两种数据结构的基本操作. 设有DataF ...

  8. 【计算机网络】 DNS学习笔记 (>﹏<)

    参考书籍 <计算机网络-自顶向下>  作者 James F. Kurose   DNS的作用   DNS是因特网的目录服务 DNS是因特网的目录服务,它提供了主机名到IP地址映射的查询服务 ...

  9. " XSS易容术---bypass之编码混淆篇+辅助脚本编写"

    一.前言本文原创作者:vk,本文属i春秋原创奖励计划,未经许可禁止转载!很多人对于XSS的了解不深.一提起来就是:“哦,弹窗的”.”哦,偷cookie的.”骚年,你根本不知道什么是力量.虽然我也不知道 ...

  10. JavaScript 那些不经意间发生的数据类型自动转换

    JavaScript可以自由的进行数据类型转换,也提供了多种显式转换的方式.但是更多的情况下,是由JavaScript自动转换的,当然这些转换遵循着一定的规则,了解数据类型自由转换的规则是非常必要的. ...