深入理解Spring IOC(四)、 实例化开启(下)

简介: 深入理解Spring IOC(四)、 实例化开启(下)

代码块10.3


代码块12
        protected Object getObjectForBeanInstance(
      Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
    // 1.如果名称是个factorybean前缀(&)开头的但是却不是FactoryBean,则抛出异常
    //  (当bean名称前缀是“&”的时候,代表这玩意是个FactoryBean的实例)
    if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
      throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
    }
    // 2.if的前半个条件意思是如果不是FactoryBean,则直接返回beanInstance
    //   后半个条件是当是个FactoryBean的时候,并且用&开头,则返回beanInstance
    // (以“&”为前缀代表想获取的是FactoryBean本身,而不是它getObject返回的)
    if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
      return beanInstance;
    }
    // 3.当代码走到这里的时候,beanInstance一定是一个FactoryBean
    //  并且想要返回的是FactoryBean中getObject所返回的,object即为返回的结果
    Object object = null;
    if (mbd == null) {
      //4. 尝试从factoryBeanObjectCache(factoryBean创建的对象的缓存)里拿
      object = getCachedObjectForFactoryBean(beanName);
    }
    // 如果从factoryBean创建的对象的缓存没拿到,就走这个if
    if (object == null) {
      //5. 因为一定是FactoryBean,所以可以直接强转
      FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
      //6. 如果mbd为空,并且beanDefinitionMap中包含着这个bean,则去根据这个获取RootBeanDefinition
      if (mbd == null && containsBeanDefinition(beanName)) {
        // 7. 获取beanName对应的RootBeanDefinition
        mbd = getMergedLocalBeanDefinition(beanName);
      }
      //8. 判断Beaneifinition是不是合成的(多次debug这里都是false)
      boolean synthetic = (mbd != null && mbd.isSynthetic());
      object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
  }


第1处的注释写的很清楚,我们来看看它调用的方法:


代码块13
        public static boolean isFactoryDereference(String name) {
    // BeanFactory.FACTORY_BEAN_PREFIX 值是“&”
    return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
  }


是不是很简单?其实源码中很多地方也没那么难的😊,第2处也很简单了,我们来看看第4处调用的方法的代码:


代码块14
        // 下面方法调用的cache
  private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<String, Object>(16);
  protected Object getCachedObjectForFactoryBean(String beanName) {
    // factoryBeanObjectCache就是factoryBean创建的对象的缓存
    Object object = this.factoryBeanObjectCache.get(beanName);
    return (object != NULL_OBJECT ? object : null);
  }


这个也是个很简单的方法,我们继续看代码块12中的第6处的这个if条件里调用的方法:


代码块15
        @Override
  public boolean containsBeanDefinition(String beanName) {
    Assert.notNull(beanName, "Bean name must not be null");
    return this.beanDefinitionMap.containsKey(beanName);
  }


这个beanDefinitionMap就是我们之前讲注册beanDefinition时候的那个map,我们再继续看代码块12中的第8处代码,注意我把第7处的跳过了哈,因为现在不是讲这个第7处方法调用的代码的最好时候,你现在先去根据注释理解,等该讲的时候,我会让你一下子明白的。


代码块16
        protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    //  FactoryBean实例是单例 && FactoryBean实例已经存在单例缓存this.singletonObjects中
    if (factory.isSingleton() && containsSingleton(beanName)) {
      // getSingletonMutex()返回的是单例缓存this.singletonObjects
      synchronized (getSingletonMutex()) {
        Object object = this.factoryBeanObjectCache.get(beanName);
        if (object == null) {
          // 1. 使用factoryBean创建bean
          object = doGetObjectFromFactoryBean(factory, beanName);
          // 如果缓存中已经存在,则用缓存中的替换上面生成的
          Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
          if (alreadyThere != null) {
            object = alreadyThere;
          }else {
            // 2. 既然object已经生成了,则执行所有BeanPostProcessor的
            //  postProcessAfterInitialization方法
            if (object != null && shouldPostProcess) {
              try {
                object = postProcessObjectFromFactoryBean(object, beanName);
              }catch (Throwable ex) {
                throw new BeanCreationException(beanName,
                    "Post-processing of FactoryBean's singleton object failed", ex);
              }
            }
            // 放入factoryBeanObjectCache缓存
            this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
          }
        }
        return (object != NULL_OBJECT ? object : null);
      }
    }else {
      // 使用factoryBean创建bean,然后再执行所有的BeanPostProcessor(和上面一样)
      // 不同点是prototype这种情况的话,不会放到缓存中
      Object object = doGetObjectFromFactoryBean(factory, beanName);
      if (object != null && shouldPostProcess) {
        try {
          object = postProcessObjectFromFactoryBean(object, beanName);
        }catch (Throwable ex) {
          throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
        }
      }
      return object;
    }
  }


直接来看代码块16里第1处调用的方法:


代码块17
        private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
      throws BeanCreationException {
    Object object;
    try {
      // 就是简单调用了FactoryBean的getObject而已,只不过if
      // 代码块的是特权调用,else里是直接调用
      if (System.getSecurityManager() != null) {
        AccessControlContext acc = getAccessControlContext();
        try {
          object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
            @Override
            public Object run() throws Exception {
                return factory.getObject();
              }
            }, acc);
        }catch (PrivilegedActionException pae) {
          throw pae.getException();
        }
      }else {
        object = factory.getObject();
      }
    }catch (FactoryBeanNotInitializedException ex) {
      throw new BeanCurrentlyInCreationException(beanName, ex.toString());
    }catch (Throwable ex) {
      throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
    }
    // 如果结果object此时还是null,并且这个FactoryBean还是在创建的这个过程中,则
    // 抛出异常,此时说明初始化流程是存在问题的
    if (object == null && isSingletonCurrentlyInCreation(beanName)) {
      throw new BeanCurrentlyInCreationException(
          beanName, "FactoryBean which is currently in creation returned null from getObject");
    }
    return object;
  }


这段代码是也是段纸老虎代码,看着很长,其实很简单,就是调用了FactoryBean的getObject方法而已,我们再来看代码块16的if中调用的代码,注意真正被调用的方法在AbstractAutowireCapableBeanFactory中:


代码块18
        @Override
  protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
    return applyBeanPostProcessorsAfterInitialization(object, beanName);
  }
  @Override
  public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {
    // 执行所有BeanPostProcessor的postProcessAfterInitialization方法
    Object result = existingBean;
    // 遍历执行
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
      result = beanProcessor.postProcessAfterInitialization(result, beanName);
      if (result == null) {
        return result;
      }
    }
    return result;
  }


至此,代码块10中的3处就完了,是不是感觉费了很久功夫呢?其实阅读源码就是这样,方法中套方法,经常都是你看完了一个很长的方法,再回到原来的方法,发现其实只是这个方法中的一行代码,我早些时候经常都是边看边吐血,因为真的太难了,不过好在一遍又一遍的坚持了下来,完了还是很开心的。


代码块10.4

小小的吐槽完了,继续看代码块10中的第4处,这里主要是针对prototype的循环依赖检查,这个是当A中有B,B中有A并且A和B的scope都是prototype的时候会在这里抛异常,spring解决不了prototype的循环依赖,原因也简单,你想嘛,你想要一个新的A,创建A的时候发现A需要一个新的B,所以要去创建B,但是创建B的时候,又要一个新的A,然后就陷入无限循环,最后要么StackOverFlowException,要么OutOfMemoryError,所以spring就在这里直接抛异常了。


代码块10.5

接下来是代码块10的第5处调用的方法,这个方法是用来获取bean的原始名称的:


代码块19
        protected String originalBeanName(String name) {
    String beanName = transformedBeanName(name);
    // 如果name中有"&",那就给beanName也加上“&”
    // 因为transformedBeanName中去掉了“&”
    if (name.startsWith(FACTORY_BEAN_PREFIX)) {
      beanName = FACTORY_BEAN_PREFIX + beanName;
    }
    return beanName;
  }


第一行的代码解释见代码块5,剩下的很简单了,我们继续代码块10中的第6处调用的方法:

代码块10.6


代码块20
        protected void markBeanAsCreated(String beanName) {
    // alreadyCreated 是已经创建的和正准备去创建的集合
    if (!this.alreadyCreated.contains(beanName)) {
      this.alreadyCreated.add(beanName);
    }
  }


依然是个很简单的方法,代码块10中第6处调用这个方法,是因为准备去创建这个bean了。我们继续代码块10中第7处,这下要讲这个之前代码块12和代码块2中跳过的getMergedLocalBeanDefinition(String name)方法了,我们先贴出来这个方法的代码哈:

代码块10.7


代码块21
    // 首先调用的方法
    protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
    // 看看缓存中有没有,如果有的话直接返回
    RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
    if (mbd != null) {
      return mbd;
    }
    // 调用下面的方法
    return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
  }
  protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
      throws BeanDefinitionStoreException {
    // 继续调用下面的方法
    return getMergedBeanDefinition(beanName, bd, null);
  }
  protected RootBeanDefinition getMergedBeanDefinition(
      String beanName, BeanDefinition bd, BeanDefinition containingBd) throws BeanDefinitionStoreException {
    // 加锁防止并发
    synchronized (this.mergedBeanDefinitions) {
      // 这个是返回结果
      RootBeanDefinition mbd = null;
      // Check with full lock now in order to enforce the same merged instance.
      // 之所以还在这里get一下,是因为防止从上面的方法到这里的时候已经有别的线程把这个RootBeanDefinition创建好了
      // 现在在这个串行的操作中,如果没有get到,说明就是确实还没有
      if (containingBd == null) {
        mbd = this.mergedBeanDefinitions.get(beanName);
      }
      // 若不存在于缓存中,则进行下一步操作
      if (mbd == null) {
        if (bd.getParentName() == null) {
          // 如果没有父定义的BeanDefinition,则不需要合并,直接通过深克隆的方式
          // 创建RootBeanDefinition
          if (bd instanceof RootBeanDefinition) {
            mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
          } else {
            mbd = new RootBeanDefinition(bd);
          }
        } else {
          // 存在父定义BeanDefinition,递归着去和父定义的合并
          BeanDefinition pbd;
          try {
            // 获取父BeanDefinition真正的名称
            String parentBeanName = transformedBeanName(bd.getParentName());
            if (!beanName.equals(parentBeanName)) {
              // 递归调用
              pbd = getMergedBeanDefinition(parentBeanName);
            } else {
              if (getParentBeanFactory() instanceof ConfigurableBeanFactory) {
                // 强转再递归调用
                pbd = ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(parentBeanName);
              } else {
                throw new NoSuchBeanDefinitionException(bd.getParentName(),
                    "Parent name '" + bd.getParentName() + "' is equal to bean name '" + beanName +
                    "': cannot be resolved without an AbstractBeanFactory parent");
              }
            }
          } catch (NoSuchBeanDefinitionException ex) {
            throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
                "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
          }
          // 根据父定义深度拷贝一个新的
          mbd = new RootBeanDefinition(pbd);
          // 用子覆盖父
          mbd.overrideFrom(bd);
        }
        // 默认单例
        if (!StringUtils.hasLength(mbd.getScope())) {
          mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
        }
        // 设置scope,此时containingBd还是null
        if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
          mbd.setScope(containingBd.getScope());
        }
        // containingBd是null && this.cacheBeanMetadata && 该bean是否可以被缓存
        // 这里这三个条件走到这块一般都成立了
        if (containingBd == null && isCacheBeanMetadata() && isBeanEligibleForMetadataCaching(beanName)) {
          this.mergedBeanDefinitions.put(beanName, mbd);
        }
      }
      return mbd;
    }
  }


这个方法的代码不算难,但是为什么要把其他类型的BeanDefinition都转成RootBeanDefinition呢?因为RootBeanDefinition是被spring作为在运行时候的统一使用的BeanDefnition(即在创建bean实例时候使用的统一的BeanDefnition),里面还包含了解析过的构造方法缓存,方法参数缓存其他缓存信息,如果说其他类型的BeanDefnition都是用于把元数据(就是如xml或者注解)表达为spring可以认识的信息的话,那么RootBeanDefinition就是把spring已经认识出来的信息表达为了可以实际去使用的信息。

我们继续看代码块10中第8处方法调用的方法:


代码块10.8


代码块22
        protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, Object[] args)
      throws BeanDefinitionStoreException {
    // 如果是抽象则抛出异常
    if (mbd.isAbstract()) {
      throw new BeanIsAbstractException(beanName);
    }
    // 如果args不是null但是beanDefinition对应的类型却不是prototype,则抛出异常
    // 这个是因为当args不是null的时候,代表需要动态参数实例化bean,而此时该bean的作用域只能是prototype
    if (args != null && !mbd.isPrototype()) {
      throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
          "Can only specify arguments for the getBean method when referring to a prototype bean definition");
    }
  }


代码块22我没有标数字,我稍微解释一下这里面的第二处注释,方法参数args不为null的情况是当你调用了applicationContext中带参数的getbean方法或者是beanFactory中带参数的getbean方法时候,这里才不是null,但是高版本的spring已经把这个对参数检查去掉了。


代码块10.9

继续看代码块10中第9处,此时已经找到我们这个beanName对应的bean需要依赖的bean是哪些bean了,因此将依赖关系注册进去:


代码块23
    public void registerDependentBean(String beanName, String dependentBeanName) {
    // 获取真正的bean名称
    String canonicalName = canonicalName(beanName);
    // 这段代码是将beanName和dependentBeanName的依赖关系注册到dependentBeanMap中
    // 注意这个是beanName依赖dependentBeanName
    synchronized (this.dependentBeanMap) {
      Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
      if (dependentBeans == null) {
        dependentBeans = new LinkedHashSet<String>(8);
        this.dependentBeanMap.put(canonicalName, dependentBeans);
      }
      dependentBeans.add(dependentBeanName);
    }
    // 这段代码是将beanName和dependentBeanName的依赖关系注册到dependentBeanMap中
    // 注意这个是dependentBeanName依赖beanName,关系是反着的
    // 就是说当A中有B,B中有A和C的时候,C中又有A,spring通过这两个map就能知道
    // A依赖了B,而依赖A的有A和C
    synchronized (this.dependenciesForBeanMap) {
      Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(dependentBeanName);
      if (dependenciesForBean == null) {
        dependenciesForBean = new LinkedHashSet<String>(8);
        this.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean);
      }
      dependenciesForBean.add(canonicalName);
    }
  }


里面第一行注释调用的方法在本篇的代码块7已经讲过,其他的都很容易理解了,我们继续回过头来看代码块10中的第10处,在看这里调用的getSingleton方法之前,你需要注意到这个getSingleton方法和之前的不一样,此外,这个方法调用的时候所传的第二参数是个实现了ObjectFactory的匿名内部类,并且在它的实现里面调用了createBean方法,限于篇幅,createBean方法会在下一篇讲,不然估计你可能会晕的更厉害。我们来看这里的getSingleton方法,注意这个getSingleton和上面代码块8的不是一个方法:

代码块10.10


代码块24
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "'beanName' must not be null");
    synchronized (this.singletonObjects) {
      Object singletonObject = this.singletonObjects.get(beanName);
      if (singletonObject == null) {
        // 如果当前beanFactory处在destruction状态中,则不允许创建bean
        // 这个状态指的是beanFactory执行了destroySingletons方法,即applicationContext执行close方法会调用到这个方法
        if (this.singletonsCurrentlyInDestruction) {
          throw new BeanCreationNotAllowedException(beanName,
              "Singleton bean creation not allowed while the singletons of this factory are in destruction " +
              "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
        }
        if (logger.isDebugEnabled()) {
          logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
        }
        // 1. 创建单例前的检查
        beforeSingletonCreation(beanName);
        // suppressedExceptions用户记录在创建期间出现的异常
        boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
        if (recordSuppressedExceptions) {
          this.suppressedExceptions = new LinkedHashSet<Exception>();
        }
        try {
          // 调用ObjectFactory来创建bean
          singletonObject = singletonFactory.getObject();
        }catch (BeanCreationException ex) {
          if (recordSuppressedExceptions) {
            for (Exception suppressedException : this.suppressedExceptions) {
              ex.addRelatedCause(suppressedException);
            }
          }
          throw ex;
        }finally {
          if (recordSuppressedExceptions) {
            this.suppressedExceptions = null;
          }
          // 2. 创建单例后的检查
          afterSingletonCreation(beanName);
        }
        // 将创建出来的bean放到缓存中
        addSingleton(beanName, singletonObject);
      }
      return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }
  }


我们来看上面的代码块中1,创建单例前的检查:


代码块25
        protected void beforeSingletonCreation(String beanName) {
    // 检查bean是否要包含在检查已经创建的集合中,如果不是,则看bean是否在创建中
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
      throw new BeanCurrentlyInCreationException(beanName);
    }
  }


然后是代码块24中的2,创建单例后的检查:


代码块26
        protected void afterSingletonCreation(String beanName) {
    // 检查bean是否要包含在检查已经创建的集合中,如果不是,则从正在创建的集合中移除,
    // 移除失败则抛异常
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
      throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
    }
  }


getSingleton方法完了,我们继续回到代码块10看11处的创建prototype前的检查:

代码块10.11


代码块27
        @SuppressWarnings("unchecked")
  protected void beforePrototypeCreation(String beanName) {
    // 从当前线程正在创建的prototype中拿所有的正在创建的集合
    Object curVal = this.prototypesCurrentlyInCreation.get();
    // 如果curlVal是空,则设置当前bean为正在创建的bean
    if (curVal == null) {
      this.prototypesCurrentlyInCreation.set(beanName);
    // 如果不是空并且是个String(代表有一个在创建中),则创建集合,并且把curVal
    // 和当前beanName都加进去
    } else if (curVal instanceof String) {
      Set<String> beanNameSet = new HashSet<String>(2);
      beanNameSet.add((String) curVal);
      beanNameSet.add(beanName);
      this.prototypesCurrentlyInCreation.set(beanNameSet);
    // 这种的说明是有两个以上的在创建,直接加入正在创建的集合中去
    } else {
      Set<String> beanNameSet = (Set<String>) curVal;
      beanNameSet.add(beanName);
    }
  }


接下来是代码块10看12处:

代码块10.12


代码块29
        @SuppressWarnings("unchecked")
  protected void afterPrototypeCreation(String beanName) {
    // 获取正在创建的prototype的集合
    Object curVal = this.prototypesCurrentlyInCreation.get();
    // 如果是String则直接remove掉
    if (curVal instanceof String) {
      this.prototypesCurrentlyInCreation.remove();
    }
    // 如果是set则从set中删除
    else if (curVal instanceof Set) {
      Set<String> beanNameSet = (Set<String>) curVal;
      beanNameSet.remove(beanName);
      if (beanNameSet.isEmpty()) {
        this.prototypesCurrentlyInCreation.remove();
      }
    }
  }


至此doGetBean方法已经讲完,下一篇,我们开始createBean方法

目录
相关文章
|
12天前
|
Java 测试技术 开发者
Spring IoC容器通过依赖注入机制实现控制反转
【4月更文挑战第30天】Spring IoC容器通过依赖注入机制实现控制反转
22 0
|
12天前
|
安全 Java 开发者
在Spring框架中,IoC和AOP是如何实现的?
【4月更文挑战第30天】在Spring框架中,IoC和AOP是如何实现的?
22 0
|
12天前
|
XML Java 程序员
什么是Spring的IoC容器?
【4月更文挑战第30天】什么是Spring的IoC容器?
20 0
|
15天前
|
Java Spring 容器
【Spring系列笔记】IOC与DI
IoC 和 DI 是面向对象编程中的两个相关概念,它们主要用于解决程序中的依赖管理和解耦问题。 控制反转是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入和依赖查找。
33 2
|
15天前
|
Java 测试技术 数据库连接
Spring中ioc的优点
总之,Spring中的IoC提供了一种更加灵活、可维护、可测试和可扩展的方式来管理组件之间的依赖关系,从而提高了应用程序的质量和可维护性。这使得开发人员能够更专注于业务逻辑而不是底层的技术细节。
32 1
|
24天前
|
Java 应用服务中间件 Spring
|
25天前
|
XML Java 数据格式
Spring IOC的源码解析
【4月更文挑战第17天】Spring IOC(控制反转)的核心功能是通过依赖注入(DI)来管理对象的创建和它们之间的依赖关系。要深入理解Spring IOC的工作原理,我们可以从其源码分析入手,特别是关注如何创建和管理Bean以及依赖注入的实现
20 1
|
29天前
|
XML Java 数据格式
Spring IOC—基于XML配置和管理Bean 万字详解(通俗易懂)
Spring 第二节 IOC—基于XML配置和管理Bean 万字详解!。
94 5
|
1月前
|
XML Java 数据格式
Spring(一)IOC小案例
Spring(一)IOC小案例
|
2月前
|
XML 缓存 Java
天天用 Spring,bean 实例化原理你懂吗
天天用 Spring,bean 实例化原理你懂吗
19 0