【六】springboot启动源码 - finishBeanFactoryInitialization

finishBeanFactoryInitialization 源码解析

Instantiate all remaining (non-lazy-init) singletons.
初始化剩下非懒加载的实例对象

finishBeanFactoryInitialization方法第918行,beanFactory.preInstantiateSingletons();
【六】springboot启动源码 - finishBeanFactoryInitialization_第1张图片
preInstantiateSingletons方法,遍历beanDefinitionNames,通过mergedBeanDefinitions来获取每一个RootBeanDefinition,并判断他是否是factorybean,如果不是,调用getBean()方法。如果是,看到后面的FactoryBean部分

【六】springboot启动源码 - finishBeanFactoryInitialization_第2张图片
doGetBean方法
第252行,transformedBeanName(name),用于返回真实beanName,如果是beanName以&开头(表示factoryBean),去掉&并返回。通过Map aliasMap来获取该beanName是否为别名,如果key有值,返回value
【六】springboot启动源码 - finishBeanFactoryInitialization_第3张图片
第256行,getSingleton(beanName),通过singletonObjects来获取之前是否已经注入到IOC中

Eagerly check singleton cache for manually registered singletons.

在这里面做了三级缓存,也是spring解决循环依赖的地方,在后面分析
这里做调试的类没有进行过初始化,singletonObjects返回null
【六】springboot启动源码 - finishBeanFactoryInitialization_第4张图片
AbstractBeanFactory第300行,typeCheckOnly一般都为false(用于类型检查实例是否获得,而不是实际使用)
进入markBeanAsCreated方法
判断alreadyCreated(已标记为创建)是否包含beanName,这里通过双重校验锁,如果不包含,将beanName添加到alreadyCreated
【六】springboot启动源码 - finishBeanFactoryInitialization_第5张图片
clearMergedBeanDefinition方法,将bd的stale设置为true,并从mergedBeanDefinitionHolders移除beanName
【六】springboot启动源码 - finishBeanFactoryInitialization_第6张图片
AbstractBeanFactory第309行,getMergedLocalBeanDefinition方法
【六】springboot启动源码 - finishBeanFactoryInitialization_第7张图片
进入getMergedLocalBeanDefinition方法
从mergedBeanDefinitions取出beanName对应的RootBeanDefinition
【六】springboot启动源码 - finishBeanFactoryInitialization_第8张图片
回到AbstractBeanFactory,判断类是否有@DependsOn注解
第332行,开始创建对象实例
【六】springboot启动源码 - finishBeanFactoryInitialization_第9张图片

getSingleton.getObject()

进入getSingleton方法
通过双重校验再次判断singletonObjects是否存在beanName
第234行,开始调用ObjectFactory(类似Supplier)的getObject方法
【六】springboot启动源码 - finishBeanFactoryInitialization_第10张图片
【六】springboot启动源码 - finishBeanFactoryInitialization_第11张图片
第514行,resolveBeanClass,解析beanClass,如果是对象被代理,返回代理对象的class
【六】springboot启动源码 - finishBeanFactoryInitialization_第12张图片
第531行,resolveBeforeInstantiation,如果有自定义InstantiationAwareBeanPostProcessor实现,调用postProcessBeforeInstantiation(实例化之前执行)。可以实例化自定义bean,但是这个回调会在所有bean实例化的时候都执行。非自定义的类也会在这里实例化,会有不可预估的风险,如果方法返回的不为null,表示已经实例化,直接返回这个bean作为创建的单例对象,并注册到IOC容器。

Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.

【六】springboot启动源码 - finishBeanFactoryInitialization_第13张图片
第542行,doCreateBean,正式开始实例化bean
【六】springboot启动源码 - finishBeanFactoryInitialization_第14张图片

doCreateBean

第582行,进入createBeanInstance
【六】springboot启动源码 - finishBeanFactoryInitialization_第15张图片

createBeanInstance

determineConstructorsFromBeanPostProcessors,在这里回调SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors方法,可以用来设置类的自定义构造器

【六】springboot启动源码 - finishBeanFactoryInitialization_第16张图片
instantiateBean方法,通过默认无参构造来实例化bean
【六】springboot启动源码 - finishBeanFactoryInitialization_第17张图片
进入instantiateBean方法,第1326行。beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
通过实例化策略执行器开始实例化bean,主要还是通过构造器实例化,过程略。
返回实例对象后,封装成BeanWrapper并返回
在这里插入图片描述

applyMergedBeanDefinitionPostProcessors

实例化bean之后,第594行,applyMergedBeanDefinitionPostProcessors方法。会在这里回调MergedBeanDefinitionPostProcessor接口postProcessMergedBeanDefinition方法
【六】springboot启动源码 - finishBeanFactoryInitialization_第18张图片

populateBean

【六】springboot启动源码 - finishBeanFactoryInitialization_第19张图片
进入populateBean方法,第1399行,回调InstantiationAwareBeanPostProcessor接口的postProcessAfterInstantiation。用于自定义判断bean与beanName是否满足相同预期结果
【六】springboot启动源码 - finishBeanFactoryInitialization_第20张图片
第1431行,回调InstantiationAwareBeanPostProcessor接口的postProcessProperties方法
【六】springboot启动源码 - finishBeanFactoryInitialization_第21张图片

这里有一个spring的实现类AutowiredAnnotationBeanPostProcessor,这里会根据进行@Autowire注解的依赖注入,会实例化依赖的类
【六】springboot启动源码 - finishBeanFactoryInitialization_第22张图片
【六】springboot启动源码 - finishBeanFactoryInitialization_第23张图片
依然会通过beanFactory.getBean(beanName);来实例化依赖的类

initializeBean

【六】springboot启动源码 - finishBeanFactoryInitialization_第24张图片
进入initializeBean,第1791行,invokeAwareMethods

invokeAwareMethods

【六】springboot启动源码 - finishBeanFactoryInitialization_第25张图片
判断bean是否实现Aware,如果当前对象是cglib生成的代理对象,默认实现EnhancedConfiguration接口,该接口继承了BeanFactoryAware
【六】springboot启动源码 - finishBeanFactoryInitialization_第26张图片
【六】springboot启动源码 - finishBeanFactoryInitialization_第27张图片
【六】springboot启动源码 - finishBeanFactoryInitialization_第28张图片
把beanFactory设置到bean中
【六】springboot启动源码 - finishBeanFactoryInitialization_第29张图片
【六】springboot启动源码 - finishBeanFactoryInitialization_第30张图片

applyBeanPostProcessorsBeforeInitialization

【六】springboot启动源码 - finishBeanFactoryInitialization_第31张图片
在这里执行BeanPostProcessor接口的postProcessBeforeInitialization回调
【六】springboot启动源码 - finishBeanFactoryInitialization_第32张图片

InitDestroyAnnotationBeanPostProcessor回调

InitDestroyAnnotationBeanPostProcessor的postProcessBeforeInitialization,会触发bean的@PostConstruct注解方法(充当init-method)
【六】springboot启动源码 - finishBeanFactoryInitialization_第33张图片

ConfigurationPropertiesBindingPostProcessor回调

ConfigurationPropertiesBindingPostProcessor的postProcessBeforeInitialization,会执行@ConfigurationProperties的自定绑定model字段逻辑。
【六】springboot启动源码 - finishBeanFactoryInitialization_第34张图片
判断类上是否有@ConfigurationProperties,并创建ConfigurationPropertiesBean返回
【六】springboot启动源码 - finishBeanFactoryInitialization_第35张图片
【六】springboot启动源码 - finishBeanFactoryInitialization_第36张图片
获取待绑定的字段,从PropertySource中寻找该字段对应的值(PropertySource值在之前已经缓存)
【六】springboot启动源码 - finishBeanFactoryInitialization_第37张图片
最终通过JavaBeanBinder的setValue方法,来为字段赋值
【六】springboot启动源码 - finishBeanFactoryInitialization_第38张图片

invokeInitMethods

【六】springboot启动源码 - finishBeanFactoryInitialization_第39张图片
会回调InitializingBean接口的afterPropertiesSet
【六】springboot启动源码 - finishBeanFactoryInitialization_第40张图片
如果对象有初始化方法(在其他配置类中定义的@Bean(initMethod = “doInit”)),会进行调用
【六】springboot启动源码 - finishBeanFactoryInitialization_第41张图片
【六】springboot启动源码 - finishBeanFactoryInitialization_第42张图片

【六】springboot启动源码 - finishBeanFactoryInitialization_第43张图片

applyBeanPostProcessorsAfterInitialization

【六】springboot启动源码 - finishBeanFactoryInitialization_第44张图片
调用BeanPostProcessor的postProcessAfterInitialization方法

getSingleton

上面已经将对象实例化。
第633行,getSingleton方法。
【六】springboot启动源码 - finishBeanFactoryInitialization_第45张图片

registerDisposableBeanIfNecessary

第661行,registerDisposableBeanIfNecessary方法。
待补充

addSingleton(beanName, singletonObject)

注册单例对象到IOC容器
【六】springboot启动源码 - finishBeanFactoryInitialization_第46张图片

SmartInitializingSingleton回调

遍历所有容器单例对象,判断是否实现SmartInitializingSingleton,如果实现会调用afterSingletonsInstantiated方法
【六】springboot启动源码 - finishBeanFactoryInitialization_第47张图片
至此finishBeanFactoryInitialization结束

循环依赖的处理

前提:开启允许循环依赖,springboot 2.6 之后就默认关闭了。
A(cicA)与B(cicB)相互依赖,A先进行初始化

  1. A完成bean实例创建
    【六】springboot启动源码 - finishBeanFactoryInitialization_第48张图片

  2. 判断是否开启了循环依赖,并添加A的bean实例工厂到beanFactory的singletonFactories中(作为第三级缓存)
    【六】springboot启动源码 - finishBeanFactoryInitialization_第49张图片

  3. 在populateBean方法中,回调InstantiationAwareBeanPostProcessor的postProcessProperties方法。这里我们需要关注AutowiredAnnotationBeanPostProcessor类。执行依赖注入
    【六】springboot启动源码 - finishBeanFactoryInitialization_第50张图片
    通过A上被@Autowire修饰的成员变量,获取到待注入的类(这里的cicB是与当前类互为循环依赖的),封装成InjectedElement
    【六】springboot启动源码 - finishBeanFactoryInitialization_第51张图片
    遍历这两个InjectedElement,依次进行解析,并调用beanFactory.getBean(beanName)。这里的bean是cicB
    【六】springboot启动源码 - finishBeanFactoryInitialization_第52张图片

  4. B完成bean实例创建,和A的第1步一样

  5. 添加B的bean实例工厂到beanFactory的singletonFactories中,和A的第2步一样

  6. 依然通过AutowiredAnnotationBeanPostProcessor的postProcessProperties方法,获取B下的被@Autowire修饰的成员变量,来执行依赖注入
    【六】springboot启动源码 - finishBeanFactoryInitialization_第53张图片
    和A的第3步一样,调用beanFactory.getBean(beanName)。这里的bean是cicA
    来到doGetBean的getSingleton(beanName)方法,从这里尝试获取A的对象
    a. 首先从一级缓存singletonObjects获取bean,因为A对象只是实例化,还没有初始化,因此还没有注入到singletonObjects中
    【六】springboot启动源码 - finishBeanFactoryInitialization_第54张图片
    b.一级缓存中获取不到bean,从二级缓存earlySingletonObjects获取,此时二级缓存也没有A的对象
    【六】springboot启动源码 - finishBeanFactoryInitialization_第55张图片
    c. 这里通过双重校验锁再次确保一、二级缓存都不存在bean。从三级缓存singletonFactories中获取到对象的ObjectFactory,通过执行ObjectFactory.getObject方法。调用如下的函数式接口,beanName为cicA,bean为实例化之后的cicA对象,返回该对象
    【六】springboot启动源码 - finishBeanFactoryInitialization_第56张图片
    这里会调用SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference方法
    【六】springboot启动源码 - finishBeanFactoryInitialization_第57张图片
    返回cicA对象,将对象放入二级缓存earlySingletonObjects中
    【六】springboot启动源码 - finishBeanFactoryInitialization_第58张图片
    获取到cicA之后,通过Field将cicA设置到cicB的字段中
    【六】springboot启动源码 - finishBeanFactoryInitialization_第59张图片

  7. cicB完成初始化,注册到一级缓存,从二、三级缓存删除

  8. 返回cicB,通过Field将cicB设置到cicA的字段中
    【六】springboot启动源码 - finishBeanFactoryInitialization_第60张图片

  9. cicA完成初始化,注册到一级缓存,从二、三级缓存删除
    【六】springboot启动源码 - finishBeanFactoryInitialization_第61张图片

总结

【六】springboot启动源码 - finishBeanFactoryInitialization_第62张图片

FactoryBean

用于创建比较复杂的bean
比如从配置文件中获取配置,通过不同值来生成不同bean

package org.hopehomi.boot.model.factorybean;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.SmartFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

/**
 * @author Ledison
 * @date 2023/3/19
 */
@Component
@Slf4j
@Data
public class MyFactoryBean implements SmartFactoryBean<Human>, InitializingBean, DisposableBean {

    private Human human;

    @Autowired
    private Environment environment;

    public MyFactoryBean() {
        System.out.println("MyFactoryBean construct");
    }

    @Override
    public boolean isEagerInit() {
        return true;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        String sex = environment.getProperty("sex");
        if (sex.equals("1")) {
            human = new Man();
        } else {
            human = new Woman();
        }
    }

    @Override
    public Human getObject() throws Exception {
        return human;
    }

    @Override
    public Class<?> getObjectType() {
        return Human.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("MyFactoryBean (DisposableBean) destroy");
    }

}


在使用中根据beanFactory的beanName来获取对象,取到的是getObject的对象。和根据bean类获取到的对象相同
【六】springboot启动源码 - finishBeanFactoryInitialization_第63张图片
【六】springboot启动源码 - finishBeanFactoryInitialization_第64张图片
如果需要获取原始Factorybean对象,需要在Factorybean前加&
【六】springboot启动源码 - finishBeanFactoryInitialization_第65张图片

源码分析

preInstantiateSingletons - getBean

preInstantiateSingletons方法,判断bean为FactoryBean
【六】springboot启动源码 - finishBeanFactoryInitialization_第66张图片

getBean

过程与前面非FactoryBean大致相同,直接来到docreateBean

doCreateBean

这里会从factoryBeanInstanceCache中获取beanName的BeanWrapper。
这个缓存是在registerBeanPostProcessors(beanFactory)的过程中就实例化了FactoryBean对象并添加到缓存中,源码略

【六】springboot启动源码 - finishBeanFactoryInitialization_第67张图片
BeanWrapper不为null,就不会在这进行实例化,后面的逻辑也和普通bean相同,依赖注入、调用初始化方法
【六】springboot启动源码 - finishBeanFactoryInitialization_第68张图片

preInstantiateSingletons - isEagerInit

获取到FactoryBean的实例【六】springboot启动源码 - finishBeanFactoryInitialization_第69张图片
如果FactoryBean实现了SmartFactoryBean且isEagerInit为true,会在这里更早进行初始化代理对象。
注意这里的beanName前面没有加&
【六】springboot启动源码 - finishBeanFactoryInitialization_第70张图片

getObjectForBeanInstance

先判断是否name以&开头,如果以&开头,表示是FactoryBean的本体name
【六】springboot启动源码 - finishBeanFactoryInitialization_第71张图片
【六】springboot启动源码 - finishBeanFactoryInitialization_第72张图片
那么直接返回本体对象
【六】springboot启动源码 - finishBeanFactoryInitialization_第73张图片

如果不是以&开头,从IOC容器获取到了FactoryBean的实例,调用getObjectFromFactoryBean方法来获取代理对象【六】springboot启动源码 - finishBeanFactoryInitialization_第74张图片

getObjectFromFactoryBean

【六】springboot启动源码 - finishBeanFactoryInitialization_第75张图片

doGetObjectFromFactoryBean

这里调用FactoryBean的getObject方法,用来返回自定义代理实例
【六】springboot启动源码 - finishBeanFactoryInitialization_第76张图片
【六】springboot启动源码 - finishBeanFactoryInitialization_第77张图片
将代理对象放入factoryBeanObjectCache。下次再执行getBean会直接从factoryBeanObjectCache中返回对象。

你可能感兴趣的:(springboot源码解析,HomeHomi脚手架,spring,boot,java,spring)