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 {
        // 1. 执行 postProcessAfterInstantiation,判断是否需要继续属性注入
        if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
            Iterator<InstantiationAwareBeanPostProcessor> var4 =
                    this.getBeanPostProcessorCache().instantiationAware.iterator();

            while (var4.hasNext()) {
                InstantiationAwareBeanPostProcessor bp = var4.next();
                // 如果返回 false,表示该实例不需要属性注入,直接返回
                if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    return;
                }
            }
        }

        // 2. 获取属性值
        PropertyValues pvs = mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;
        int resolvedAutowireMode = mbd.getResolvedAutowireMode();

        // 3. 自动装配(byName 或 byType)
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues) pvs);

            // 3.1 根据 Bean Name 自动注入
            if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
                this.autowireByName(beanName, mbd, bw, newPvs);
            }

            // 3.2 根据 Bean Type 自动注入
            if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
                this.autowireByType(beanName, mbd, bw, newPvs);
            }

            pvs = newPvs;
        }

        // 4. 执行 InstantiationAwareBeanPostProcessor 的属性后置处理
        boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = mbd.getDependencyCheck() != 0;
        PropertyDescriptor[] filteredPds = null;

        if (hasInstAwareBpps) {
            if (pvs == null) {
                pvs = mbd.getPropertyValues();
            }

            Iterator<InstantiationAwareBeanPostProcessor> var9 =
                    this.getBeanPostProcessorCache().instantiationAware.iterator();

            while (var9.hasNext()) {
                InstantiationAwareBeanPostProcessor bp = var9.next();

                // 4.1 优先调用 postProcessProperties(Spring 5.1+ 推荐方式)
                PropertyValues pvsToUse = bp.postProcessProperties((PropertyValues) pvs, bw.getWrappedInstance(), beanName);

                if (pvsToUse == null) {
                    // 4.2 降级调用 postProcessPropertyValues(已过时,但兼容旧版本)
                    if (filteredPds == null) {
                        filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                    }
                    pvsToUse = bp.postProcessPropertyValues((PropertyValues) pvs, filteredPds,
                            bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {
                        return;
                    }
                }
                pvs = pvsToUse;
            }
        }

        // 5. 执行依赖检查(如果配置了 dependency-check)
        if (needsDepCheck) {
            if (filteredPds == null) {
                filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            }
            this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues) pvs);
        }

        // 6. 应用属性值到 Bean 实例
        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  阅读(85)  评论(0)    收藏  举报