IOC -- bean的创建过程

Bean的创建过程

  • refresh
  • finishBeanFactoryInitialization
  • preInstantiateSingletons
  • getBean
  • doGetBean
  • 实例化
  • 属性注入
  • 初始化

总的过程就是这几步,下面详细走一下,从第三步开始

preInstantiateSingletons

该方法是在finishBeanFactoryInitialization方法中被执行。作用是实例化剩余的单实例bean
方法由DefaultListableBeanFactory实现

先获取ioc中的bean定义名称

List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

循环所有beanName,合并bean定义

RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

其实就是先从缓存中拿beanDefinition,最终返回的是RootBeanDefinition,这里就牵扯到几种beanDefinition了。先挖个坑,后面再填

判断是不是抽象的、单例的、懒加载的 -->再是判断是不是工厂bean,是的话加上前缀符号。然后调用getBean

if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
    if (isFactoryBean(beanName)) {
        //调用真正的getBean的流程
      if (isEagerInit) {
         getBean(beanName);
      }
   }
}
else {//非工厂Bean 就是普通的bean
   getBean(beanName);
}

getBean会去调用doGetBean

首先尝试去一级缓存中拿,也就是第一次调用getSingleton方法。
当然bean本身没被创建,当然拿不到的,所以返回为空

Object sharedInstance = getSingleton(beanName);

下面就进入创建bean的逻辑

首先判断当前bean是否是正在创建中,且是原型的。是直接抛出异常。因为这里涉及到循环依赖的问题,而spring只能解决单例bean的setter注入循环依赖

if (isPrototypeCurrentlyInCreation(beanName)) {
   throw new BeanCurrentlyInCreationException(beanName);
}

随后是子父容器的判断。一般情况下只有spring和spring mvc整合的时候才会出现子父容器的概念

下面这段就先忽略

BeanFactory parentBeanFactory = getParentBeanFactory();
//若存在父工厂,切当前的bean工厂不存在当前的bean定义,那么bean定义是存在于父beanFacotry中
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
   //获取bean的原始名称
   String nameToLookup = originalBeanName(name);
   //若为 AbstractBeanFactory 类型,委托父类处理
   if (parentBeanFactory instanceof AbstractBeanFactory) {
      return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
            nameToLookup, requiredType, args, typeCheckOnly);
   }
   else if (args != null) {
      //  委托给构造函数 getBean() 处理
      return (T) parentBeanFactory.getBean(nameToLookup, args);
   }
   else {
      // 没有 args,委托给标准的 getBean() 处理
      return parentBeanFactory.getBean(nameToLookup, requiredType);
   }
}

接着我们跳过各个校验直接来到创建单例bean

if (mbd.isSingleton()) {
   //把beanName 和一个singletonFactory 并且传入一个回调对象用于回调
   sharedInstance = getSingleton(beanName, () -> {
      try {
         //进入创建bean的逻辑
         return createBean(beanName, mbd, args);
      }
      catch (BeansException ex) {
         //创建bean的过程中发生异常,需要销毁关于当前bean的所有信息
         destroySingleton(beanName);
         throw ex;
      }
   });
   bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

这里调用getSingleton的重载方法。第二个参数是一个工厂接口

getSingleton

先加锁,然后再次试着从一级缓存中拿

 Object singletonObject = this.singletonObjects.get(beanName);

还是为空,那就说明该bean需要创建,标注bean正在被创建,也就是加入到一个集合中singletonsCurrentlyInCreation

 beforeSingletonCreation(beanName);
 //该方法会进行判断是否集合中已经存在该bean,说明该bean正在被创建,会抛出异常

调用接口工厂的方法

 try {
            //<3> 初始化 bean
            // 这个过程其实是调用 createBean() 方法
            singletonObject = singletonFactory.getObject();
            newSingleton = true;
         }

也就是createBean()

createBean

方法前部分有一些验证,这里跳过。关键调用点是

Object beanInstance = doCreateBean(beanName, mbdToUse, args);

所以spring中真正干活的还是do开头的

doCreateBean

if (instanceWrapper == null) {
   //使用合适的实例化策略来创建新的实例:工厂方法、构造函数自动注入、简单初始化 该方法很复杂也很重要
   instanceWrapper = createBeanInstance(beanName, mbd, args);
}

doCreateBean中,这里利用反射之间创建bean实例
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
      mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
   //通过构造函数创建对象
   return autowireConstructor(beanName, mbd, ctors, args);
}

//使用无参数的构造函数调用创建对象
return instantiateBean(beanName, mbd);

到这里bean已经被实例化了
然后穿插一下@Autowried注解的预解析
随即将刚刚实例化的bean进行早期暴露,条件是单例、允许早期暴露且是正在创建的bean

包装早期对象

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
   Assert.notNull(singletonFactory, "Singleton factory must not be null");
   //同步加锁
   synchronized (this.singletonObjects) {
      //单例缓存池中没有包含当前的bean
      if (!this.singletonObjects.containsKey(beanName)) {
         //加入到三级缓存中,,,,,暴露早期对象用于解决循环依赖
         this.singletonFactories.put(beanName, singletonFactory);
         this.earlySingletonObjects.remove(beanName);
         this.registeredSingletons.add(beanName);
      }
   }
}

将我们的bean加入到了三级缓存中

属性赋值

populateBean调用set方法进行赋值

populateBean(beanName, mbd, instanceWrapper);  

初始化操作

exposedObject = initializeBean(beanName, exposedObject, mbd);

这里会调用三个关键的方法

applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);

invokeInitMethods(beanName, wrappedBean, mbd);

applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

第一个是调用我们bean后置处理器的postProcessorsBeforeInitialization方法
第二个是初始化方法,这里会回调实现了 InitializingBean 接口的 afterPropertiesSet方法并且调用bean的init方法
第三个是调用bean后置处理器的postProcessorsAfterInitialization方法
完成之后bean才真正的算是创建完

善后处理

允许早期对象的调用,再次getSingleton,但是这次传递的allowEarlyReference是false

Object earlySingletonReference = getSingleton(beanName, false);

表示不再从三级缓存中拿,只会在一二级缓存中拿。注意,在此之前我们并未将bean放到一二级缓存中,只是放入了三级缓存。所以还是为空
注册销毁bean的接口

registerDisposableBeanIfNecessary(beanName, bean, mbd);

到此doCreateBean走完
方法弹栈,到最早调用getSingleton的地方,然后将该bean从正在创建的集合中剔除,也就是从singletonsCurrentlyInCreation中剔除。

afterSingletonCreation(beanName);

再加入到缓存中,将其加入到一级缓存,并二三级缓存中剔除,并添加入已处理bean集合中

addSingleton(beanName, singletonObject);
protected void addSingleton(String beanName, Object singletonObject) {
   synchronized (this.singletonObjects) {
      //加入到单例缓存池中
      this.singletonObjects.put(beanName, singletonObject);
      //从三级缓存中移除(针对的不是处理循环依赖的)
      this.singletonFactories.remove(beanName);
      //从二级缓存中移除(循环依赖的时候 早期对象存在于二级缓存)
      this.earlySingletonObjects.remove(beanName);
      //用来记录保存已经处理的bean
      this.registeredSingletons.add(beanName);
   }
}

总结

上述过程是一个普通bean的创建过程,没有循环依赖。

两次getSingleton

首先调用第一次getSingleton,也就是在doGetBean逻辑中调用的,这里调用的是传入接口工厂的重载

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
   synchronized (this.singletonObjects) {
      //尝试从单例缓存池中获取对象
      Object singletonObject = this.singletonObjects.get(beanName);
         beforeSingletonCreation(beanName);
         try {
            //<3> 初始化 bean
            // 这个过程其实是调用 createBean() 方法
            singletonObject = singletonFactory.getObject();
            newSingleton = true;
         }
         finally {
            if (recordSuppressedExceptions) {
               this.suppressedExceptions = null;
            }
            // <4> 后置处理
            //主要做的事情就是把singletonsCurrentlyInCreation标记正在创建的bean从集合中移除
            afterSingletonCreation(beanName);
         }
         if (newSingleton) {
            // <5> 加入缓存中
            addSingleton(beanName, singletonObject);
         }
      }
      return singletonObject;
   }
}

在doCreateBean的逻辑里调用的,这个getSingleton作用上更加接近于我们正常下理解的,从一级缓存中拿,然后二级、三级
如果它能够在二级缓存中拿不到,并且是allowEarlyReference,允许早期暴露的。那么会从三级缓存中拿。拿到过后放入二级缓存,从三级缓存中删除

Object earlySingletonReference = getSingleton(beanName, false);

protected Object getSingleton(String beanName, boolean allowEarlyReference) 

实例化和初始化期间穿插的后置处理器调用

在实例化之前,也就是调用doCreateBean之前,调用了下面的方法。这是AOP相关的

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

实例化完成之后,穿插了@Autowired注解的预解析工作

//进行后置处理 @AutoWired的注解的预解析
//MergedBeanDefinitionPostProcessor接口调用的入口
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

初始化之前,调用bean的后置处理器的beforeInitialization方法,也就是容器中所有实现了BeanPostProcessor的处理器

wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);

初始化之后,调用bean的后置处理器的AfterInitialization方法,也就是容器中所有实现了BeanPostProcessor的处理器

wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值