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

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

java代码:

    public Object getBean(String name) throws BeansException {  return getBean(name, null, null);  }  public Object getBean(String name, Class requiredType) throws BeansException {  return getBean(name, requiredType, null);  }  public Object getBean(String name, Object[] args) throws BeansException {  return getBean(name, null, args);  }  /** * Return an instance, which may be shared or independent, of the specified bean. * @param name the name of the bean to retrieve * @param requiredType the required type of the bean to retrieve * @param args arguments to use if creating a prototype using explicit arguments to a * static factory method. It is invalid to use a non-null args value in any other case. * @return an instance of the bean * @throws BeansException if the bean could not be created */  public Object getBean(String name, Class requiredType, Object[] args) throws BeansException {  return doGetBean(name, requiredType, args, false);  }  

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

Java代码

    protected Object doGetBean(  final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)   throws BeansException {  //bean name处理,去除FactoryBean前缀等  final String beanName = transformedBeanName(name);  Object bean = null;  //先从singleton缓存中查看是否已经实例化过该Bean,根据是否有缓存分为两个分支分别处理  Object sharedInstance = getSingleton(beanName);  if (sharedInstance != null && args == null) {  // 分支一,若缓存中获取到了并且该BeanDefinition信息表明该bean是singleton的,直接将获取到的缓存Bean  //(有可能是半成品)交给getObjectForBeanInstance处理  /*.........省略logger部分代码............*/  //调用getObjectForBeanInstance处理  bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);  }else {  // 分之二:没有缓存,则需要从头实例化该bean  // We're assumably within a circular reference.  if (isPrototypeCurrentlyInCreation(beanName)) {   throw new BeanCurrentlyInCreationException(beanName);}  // 检查BeanDefinition是否在当前工厂或父工厂  BeanFactory parentBeanFactory = getParentBeanFactory();  if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {  // Not found -> check parent.  String nameToLookup = originalBeanName(name);  if (args != null) {  // 父工厂getBean  return parentBeanFactory.getBean(nameToLookup, args);  }  else {  // No args -> delegate to standard getBean method.  return parentBeanFactory.getBean(nameToLookup, requiredType);  }  }  //将bean加入“正在创建”的集合,完成后会remove,对应afterSingletonCreation/afterPrototypeCreation方法  if (!typeCheckOnly) {  markBeanAsCreated(beanName);  }  final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);  checkMergedBeanDefinition(mbd, beanName, args);  // 解决依赖关系,将依赖的bean提前实例化  String[] dependsOn = mbd.getDependsOn();  if (dependsOn != null) {  for (int i = 0; i < dependsOn.length; i++) {  String dependsOnBean = dependsOn[i];  getBean(dependsOnBean);  registerDependentBean(dependsOnBean, beanName);  }  }  // 这里又需要根据bean的类型分为三种情况:singleton、prototype、request/session  if (mbd.isSingleton()) {  //通过自定义ObjectFactory实例化Bean,此结果可能是半成品(是FactoryBean等)  sharedInstance = getSingleton(beanName, new ObjectFactory() {  public Object getObject() throws BeansException {  try {  //真正实例化装配的逻辑在createBean方法中  return createBean(beanName, mbd, args);  }  catch (BeansException ex) {  // Explicitly remove instance from singleton cache: It might have been put there  // eagerly by the creation process, to allow for circular reference resolution.  // Also remove any beans that received a temporary reference to the bean.  destroySingleton(beanName);  throw ex;  }  }  });  //上一步半成品的Bean交给getObjectForBeanInstance方法处理  bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);  }  else if (mbd.isPrototype()) {  // It's a prototype -> create a new instance.  Object prototypeInstance = null;  try {  beforePrototypeCreation(beanName);  //真正实例化装配的逻辑在createBean方法中  prototypeInstance = createBean(beanName, mbd, args);  }  finally {  afterPrototypeCreation(beanName);  }  //上一步半成品的Bean交给getObjectForBeanInstance方法处理  bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);  }  else {  //request、session 的bean  String scopeName = mbd.getScope();  final Scope scope = (Scope) this.scopes.get(scopeName);  if (scope == null) {  throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");  }  try {  Object scopedInstance = scope.get(beanName, new ObjectFactory() {  public Object getObject() throws BeansException {  beforePrototypeCreation(beanName);  try {  //真正实例化装配的逻辑在createBean方法中  return createBean(beanName, mbd, args);  }  finally {  afterPrototypeCreation(beanName);  }  }  });  //上一步半成品的Bean交给getObjectForBeanInstance方法处理  bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);  }  catch (IllegalStateException ex) {  throw new BeanCreationException(beanName,  "Scope '" + scopeName + "' is not active for the current thread; " +  "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",  ex);  }  }  }  // Check if required type matches the type of the actual bean instance.  if (requiredType != null && bean != null &&  !requiredType.isAssignableFrom(bean.getClass())) {  throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());  }  return bean;  }  

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

Java代码

    sharedInstance = getSingleton(beanName, new ObjectFactory() {  public Object getObject() throws BeansException {  try {  return createBean(beanName, mbd, args);  }  catch (BeansException ex) {  // Explicitly remove instance from singleton cache: It might have been put there  // eagerly by the creation process, to allow for circular reference resolution.  // Also remove any beans that received a temporary reference to the bean.  destroySingleton(beanName);  throw ex;  }  }  });  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的代理逻辑应该就在这里处理了,具体看看这部分的代码:

Java代码

    /** * Apply before-instantiation post-processors, resolving whether there is a * before-instantiation shortcut for the specified bean. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @return the shortcut-determined bean instance, or <code>null</code> if none */  protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {  Object bean = null;  if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {  // Make sure bean class is actually resolved at this point.  if (mbd.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {  bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName);  if (bean != null) {  bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);  }  }  mbd.beforeInstantiationResolved = Boolean.valueOf(bean != null);  }  return bean;  }  /** * Apply InstantiationAwareBeanPostProcessors to the specified bean definition * (by class and name), invoking their <code>postProcessBeforeInstantiation</code> methods. * <p>Any returned object will be used as the bean instead of actually instantiating * the target bean. A <code>null</code> return value from the post-processor will * result in the target bean being instantiated. * @param beanClass the class of the bean to be instantiated * @param beanName the name of the bean * @return the bean object to use instead of a default instance of the target bean, or <code>null</code> * @throws BeansException if any post-processing failed * @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation */  protected Object applyBeanPostProcessorsBeforeInstantiation(Class beanClass, String beanName)  throws BeansException {  for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {  BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();  if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) {  InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor;  Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);  if (result != null) {  return result;  }  }  }  return null;  }  //AbstractAutoProxyCreator  public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {  Object cacheKey = getCacheKey(beanClass, beanName);  if (!this.targetSourcedBeans.contains(cacheKey)) {  if (this.advisedBeans.contains(cacheKey) || this.nonAdvisedBeans.contains(cacheKey)) {  return null;  }  if (isInfrastructureClass(beanClass, beanName) || shouldSkip(beanClass, beanName)) {  this.nonAdvisedBeans.add(cacheKey);  return null;  }  }  // Create proxy here if we have a custom TargetSource.  // Suppresses unnecessary default instantiation of the target bean:  // The TargetSource will handle target instances in a custom fashion.  TargetSource targetSource = getCustomTargetSource(beanClass, beanName);  if (targetSource != null) {  this.targetSourcedBeans.add(beanName);  Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);  Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);  this.proxyTypes.put(cacheKey, proxy.getClass());  return proxy;  }  return null;  }  

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

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

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

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

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

    protected Object getObjectForBeanInstance(  Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {  // Don't let calling code try to dereference the factory if the bean isn't a factory.  if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {  throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());  }  // Now we have the bean instance, which may be a normal bean or a FactoryBean.  // If it's a FactoryBean, we use it to create a bean instance, unless the  // caller actually wants a reference to the factory.  if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {  return beanInstance;  }  Object object = null;  if (mbd == null) {  object = getCachedObjectForFactoryBean(beanName);  }  if (object == null) {  // Return bean instance from factory.  FactoryBean factory = (FactoryBean) beanInstance;  // Caches object obtained from FactoryBean if it is a singleton.  if (mbd == null && containsBeanDefinition(beanName)) {  mbd = getMergedLocalBeanDefinition(beanName);  }  boolean synthetic = (mbd != null && mbd.isSynthetic());  object = getObjectFromFactoryBean(factory, beanName, !synthetic);  }  return object;  }  

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

BeanDefinition到Bean相关推荐

  1. BeanDefinition BeanFactory Bean的关系

    一.什么是BeanDefinition BeanDefinition表示Bean定义,Spring根据BeanDefinition来创建Bean对象,BeanDefinition有很多属性来描述Bea ...

  2. SpringBoot:class变成beanDefinition, beanDefinition变成bean

    SpringBoot:class变成beanDefinition, beanDefinition变成bean 跟进AbstractApplicationContext的refresh方法: publi ...

  3. Spring解析,加载及实例化Bean的顺序(零配置)

    点击上方蓝色"方志朋",选择"设为星标"回复"666"获取独家整理的学习资料! 作者:jb_hz blog.csdn.net/qq_2752 ...

  4. Spring源码剖析——Bean的配置与启动

    IOC介绍   相信大多数人在学习Spring时 IOC 和 Bean 算得上是最常听到的两个名词,IOC在学习Spring当中出现频率如此之高必然有其原因.如果我们做一个比喻的话,把Bean说成Sp ...

  5. IoC-spring 的灵魂(带你轻松理解IOC思想及bean对象的生成过程)

    在理解任何技术之前,我都会问自己一个问题:它的产生是为了解决什么样的问题,以及如何解决这些问题?希望你能在本篇文章中找到答案-- (由于大家对Ioc应该是经常使用了,所以这里不会告诉你应该怎么样使用, ...

  6. 手写简版spring --2--实现Bean的定义、注册、获取

    一.目标 在上一章节我们初步依照 Spring Bean 容器的概念,实现了一个粗糙版本的代码实现.那么本章节我们需要结合已实现的 Spring Bean 容器进行功能完善,实现 Bean 容器关于 ...

  7. 手写简版spring --1--创建简单的Bean容器

    一.声明 这个系列是我自己的学习笔记,为了在学习的过程中巩固知识而记录的,好强迫自己用心拜读,而不是进收藏夹.本系列都是基于小缚哥的文章和代码的,想要深入了解,请移步小缚哥博客 二.spring-Be ...

  8. Bean的解析与注册

    本文探讨spring对bean解析,并注册到IOC容器的过程 一.ClassPathBeanDefinitionScanner类(遍历bean集合) //类路径Bean定义扫描器扫描给定包及其子包pr ...

  9. spring bean加载过程_Spring源码剖析3:Spring IOC容器的加载过程

    本文转自五月的仓颉 https://www.cnblogs.com/xrq730 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https ...

最新文章

  1. springboot . 配置jpa使用
  2. iphone已停用解锁大概多少钱_【待办清单工具之三】微软To Do amp; iPhone提醒事项-来自大厂的时间管理系统...
  3. 分布式转码初步方案(hadoop+ffmpeg)
  4. 快速浏览JAX-RS请求与方法匹配
  5. 0-11 NFS与TFTP服务器配置
  6. 解决方法:AttributeError: module ‘torchtext.data‘ has no attribute ‘Field‘
  7. php如何反向排列数组,php中的sort()如何排列目录结构数组?
  8. Django------多表操作
  9. FLEX AIR添加系统托盘图标步骤
  10. [paper reading] GoogLeNet
  11. 打log的方式检查程序里面的问题 及示例代码 详解
  12. ubuntu lamp环境(阿里云搭建lamp)
  13. 酷派D530刷机指引之官方ROM
  14. Fiddler移动端代理设置(移动端抓包设置,包教会)
  15. linux cp并打包目录,【linux】【qt5】【将linux下的qt程序打包发布(完全适用于中标麒麟)】...
  16. 什么是DDOS攻击?怎么抵抗DDOS攻击?
  17. 用mg格式制作产品动画有什么优势?
  18. 用C语言实现汉诺塔的移动过程并且统计移动的次数
  19. Scratch软件编程等级考试一级——20211211
  20. 写在离职前,我在富士康的这两年

热门文章

  1. 【SQL】练习题184道
  2. SQLServer的sql_variant数据类型
  3. 2020年 初赛真题
  4. 学习笔记 - 用户故事(User Story)
  5. 简洁、快速、节约内存的Excel处理工具EasyExcel
  6. .*? 和 .*的区别
  7. Tensorflow变量作用域及变量初始化
  8. 前端切图之svg图标的复用基于defs和use 亲测有用
  9. 亚马逊筋膜枪UL1647测试报告流程介绍
  10. 越南博主抄袭李子柒上热搜!内容创作如何告别侵权焦虑?