IOC容器启动及Bean生成流程

目录

一、容器启动

  • IOC启动流程

  • 重点


二、扫描并注册BeanDefination

  • 加载并过滤资源

  • 注册BeanDefination


三、BeanFactory后置处理


四、注册Bean后置处理器


五、遍历BeanDefination,实例化单例Bean

  • preInstantiateSingletons

  • doGetBean(我们只关注单例)

  • createBean

    • 实例化前执行
  • doCreateBean

    • 实例化

    • 属性赋值

    • 初始化

  • getSingleton


六、总结

没有很详细了解Bean的可能只知道Bean会经历实例化,初始化,属性赋值这些所谓的Bean生命周期,再往下细聊可能就不清楚了,这次呢我们就全面的了解一下IOC容器的启动流程,然后重点看一下其中有关Bean的流程!


一、容器启动

上节我们说过了,容器启动入口就是ApplicationContext,有两个重要的实现类:

  • AnnotationConfigApplicationContext: 基于注解包路径扫描的容器上下文,通过扫描注解来完成BeanDefinition的注册

  • ClassPathXmlApplicationContext: 基于类路径下xml文件的Spring应用程序上下文,通过解析类路径下的xml来完成BeanDefinition的注册


这里我们就通过现在流行的注解方式来看,像下面这样一行代码就能启动一个容器了

  AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);


我们是扫描了一个包,直接看看这个构造方法


源代码如下:

上面初始化的两个类我们上一节也提过了

  • AnnotatedBeanDefinitionReader: 读取注解生成BeanDefinition并注册

  • ClassPathBeanDefinitionScanner: 扫描类路径生成BeanDefinition并注册


这里是扫描的包,所以无疑是会执行 ClassPathBeanDefinitionScanner.doScan 方法,我们下面再说


二、IOC启动流程

先看一下启动的流程refresh():


三、重点


我们重点关注 和 Bean相关的内容,我们下面一个个看(注册代表放入工厂):


1、扫描并注册BeanDefination


2、BeanFactory后置处理(invokeBeanFactoryPostProcessors)


3、实例化并注册Bean后置处理器(registerBeanPostProcessors)


4、遍历BeanDefination,实例化单例Bean(finishBeanFactoryInitialization)


refresh() 流程如下:


四、扫描并注册BeanDefination


我们上面说了,我们采用的方式是包扫描,所以最终调用的是 ClassPathBeanDefinitionScanner.doScan 方法,在这个方法中我们重点关注两个:


一个是加载并过滤资源 findCandidateComponents()


一个是注册放入工厂registerBeanDefinition()


1、加载并过滤资源

为什么要过滤资源?因为加载并不是直接加载被注解标识的类,而是加载了所有的类,然后再判断具体需要把哪些变成BeanDefination,所以需要过滤一次

ClassPathScanningCandidateComponentProvider.scanCandidateComponents:

this.isCandidateComponent:

该方法中就会根据过滤器,对这些资源过滤,最终获取的资源就是我们要加载的Bean(内置了一个AnnotationTypeFilter过滤器就是对 @Component注解过滤)


五、注册BeanDefination


要加载的Bean对象会被解析封装成BeanDefination,里面就是Bean对象相关的所有信息,最终调用的就是工厂中的注册BeanDefination的方法registerBeanDefinition(),信息会保存在工厂内的集合里面


DefaultListableBeanFactory.registerBeanDefinition():


六、BeanFactory后置处理

这个在上一节也说过了,对BeanDefination和BeanFactory的后置处理,其实就是对下面这三类接口做一个处理,将实现了这三类接口的实现类找出来排序,挨个执行里面的方法,

总得来说就是对BeanDefination和BeanFactory做一个后置的处理

  • BeanDefinitionRegistry

  • BeanFactoryPostProcessor

  • BeanDefinitionRegistryPostProcessor


最终会执行下面这个方法,这个方法还挺长,我就只截图部分了,重点是掌握以上这些接口,知道这些接口可以对BeanDefination和BeanFactory做一个后置的处理就可以了


PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors:


七、注册Bean后置处理器


这里只是把Bean的后置处理器给全找出来放到BeanFactory中去,在后面Bean实例化、初始化、属性赋值的时候才执行生效


PostProcessorRegistrationDelegate.registerBeanPostProcessors:

先找到全部的然后处理、排序,然后注册放入工厂


八、遍历 BeanDefination,实例化单例 Bean

这一步就是最感兴趣的Bean的生命周期了,前面的准备工作都做完了,BeanDefination和BeanPostProcessor都放入工厂beanFactory中,还是老规矩只看重点,其他的一律跳过,

主流程都不理解看其他的只会懵逼,我们先看一张关于Bean生成的图:

入口就是我们下面这个方法,也就是IOC容器启动最关键一步了,从图上看真正的逻辑体现在doGetBean处,我将整个过程最关键的位置分成三步,也就是实例化、属性赋值、初始化,中间插入后置处理器的一些方法处理,

这中间关于三级缓存的地方我会提一下,但是不会深入介绍,之后再说


1、preInstantiateSingletons


DefaultListableBeanFactory.preInstantiateSingletons


这个方法需要记住几个点:


第一点:普通的Bean和实现了FactoryBean接口的Bean 生成流程是不同的


第二点:Bean都生成完成后,会判断Bean是否实现了SmartInitializingSingleton接口,实现了的Bean还会执行该接口的afterSingletonsInstantiated方法


第三点:FactoryBean和单例Bean都会执行getBean方法,getBean又会调用doGetBean方法


2、doGetBean(我们只关注单例)


a、首先会先判断Bean是否已经生成了


b、没生成就走getSingleton方法(对于单例而已)


c、getSingleton执行的时候就会调用那个lambda表达式,也就是会执行createBean方法


d、生成的Bean对象都要判断一次是不是FactoryBean,是的话还要特殊处理一次


3、createBean


AbstractAutowireCapableBeanFactory.createBean


这里很简单,上一节说过了有些拓展的Bean后置处理器会在Bean实例化前执行,所以在一步里面手动实例化了已经存在的bean就不需要再往下走流程了直接返回,正常的Bean都会往下走


4、实例化前执行


resolveBeforeInstantiation


这一步了解一下就好了,毕竟少用,实例化前执行的接口就是 InstantiationAwareBeanPostProcessor继承了BeanPostProcessor


5、doCreateBean

总得来说就分成了三步,实例化、属性赋值、初始化(Bean的生命周期就在这了),过程里面包含一个三级缓存的重点


6、实例化


createBeanInstance


这里就是利用反射实例化,然后将实例化对象包装成了BeanWrapper


7、populateBean 属性赋值


这里就是对Bean里面的属性赋值和依赖bean的注入,同时实例化后执行的方法在里面也会执行


注入需要去容器中找对应的Bean,这里有两个查找方法根据Bean name 和根据Bean type


之后后置处理器的拓展点又会生效执行,InstantiationAwareBeanPostProcessor 内的两个属性赋值的方法

  protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
          if (bw == null) {
              if (mbd.hasPropertyValues()) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
              }
          } else {
              if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
                  Iterator var4 = this.getBeanPostProcessorCache().instantiationAware.iterator();

                  while(var4.hasNext()) {
                      // 实例后执行 
                      // 这里会判断实例化后执行的那个返回值true 或者 false
                      // false代表该实例 不需要属性注入
                      InstantiationAwareBeanPostProcessor bp = (InstantiationAwareBeanPostProcessor)var4.next();
                      if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                          return;
                      }
                  }
              }

              PropertyValues pvs = mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;
              int resolvedAutowireMode = mbd.getResolvedAutowireMode();
              if (resolvedAutowireMode == 1 || resolvedAutowireMode == 2) {
                  MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
                  // 属性注入 根据Bean name去容器中找然后注入
                  if (resolvedAutowireMode == 1) {
                      this.autowireByName(beanName, mbd, bw, newPvs);
                  }
                  // 属性注入 根据Bean Type去容器中找然后注入
                  if (resolvedAutowireMode == 2) {
                      this.autowireByType(beanName, mbd, bw, newPvs);
                  }

                  pvs = newPvs;
              }

              boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
              boolean needsDepCheck = mbd.getDependencyCheck() != 0;
              PropertyDescriptor[] filteredPds = null;
              if (hasInstAwareBpps) {
                  if (pvs == null) {
                      pvs = mbd.getPropertyValues();
                  }

                  PropertyValues pvsToUse;
                  for(Iterator var9 = this.getBeanPostProcessorCache().instantiationAware.iterator(); var9.hasNext(); pvs = pvsToUse) {
                      // 这里InstantiationAwareBeanPostProcessor 中给属性赋值的两个方法也会执行
                      // 上一节说过了 不多说了
                      InstantiationAwareBeanPostProcessor bp = (InstantiationAwareBeanPostProcessor)var9.next();
                      pvsToUse = bp.postProcessProperties((PropertyValues)pvs, bw.getWrappedInstance(), beanName);
                      if (pvsToUse == null) {
                          if (filteredPds == null) {
                              filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                          }
                          pvsToUse = bp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
                          if (pvsToUse == null) {
                              return;
                          }
                      }
                  }
              }

              if (needsDepCheck) {
                  if (filteredPds == null) {
                      filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                  }

                  this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);
              }

              if (pvs != null) {
                  this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);
              }

          }
      }


8、initializeBean 初始化


1、先会执行一个拓展点BeanFactoryAware


2、然后初始化前执行(BeanPostProcessors.postProcessBeforeInitialization)


3、初始化(利用反射执行init()方法、InitializingBean拓展点)


4、然后初始化后执行 (BeanPostProcessors.postProcessAfterInitialization)


9、getSingleton


DefaultSingletonBeanRegistry.getSingleton


正常会优先执行getSingleton,只不过这里面内部会执行那个lambda表达式,还是要去执行createBean方法,最终就是会把Bean加入到一级缓存,同时删除掉其他缓存

到这Bean的流程就结束啦


九、总结


1、整体上看Bean流程为:BeanDefination ---> 实例化 ---> 属性赋值 ---> 初始化


2、后置处理器可以对上述流程各阶段前后做出相应的修改和调整


3、再细数一下过程中的拓展接口:

  • BeanDefinitionRegistryPostProcessor:对BeanDefination后置处理

  • BeanFactoryPostProcessor:对BeanFactory后置处理

  • BeanPostProcessor:初始化前后处理

  • InstantiationAwareBeanPostProcessor:实例化前后、属性赋值、初始化前后

  • InitializingBean:初始化执行

  • BeanFactoryAware:获取容器中的工厂

  • ApplicationContextAware:获取容器上下文

  • SmartInitializingSingleton:Bean全生成完了后执行


4、源码很多,但是我们挑自己感兴趣的那部分重点来看,就能形成一个结构化思维,最后再看一下图

posted @ 2025-03-23 17:34  jock_javaEE  阅读(47)  评论(0)    收藏  举报