• spring5.0 源码解析 finishBeanFactoryInitialization 总览


    这个方法用于实例化所有剩余的(非延迟初始化)单例,我愿称之为 spring源码中最难的一部分,建议新手先去看一本书叫做 《spring揭秘》 他是从设计的角度讲解spring核心思想,而不是 上来就直接搞源码。

    spring 在初始化所有剩余的单例bean做了哪些准备


    为此上下文初始化 类型转换器


    ConversionService 是一个 用于类型转换的服务接口

    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
    				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
    			beanFactory.setConversionService(
    					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    检查上下文中是否存在类型转换器

    // 检查上下文中是否存在类型转换器
    		if (!beanFactory.hasEmbeddedValueResolver()) {
    			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    		}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    优先初始化的bean

    //  尽早初始化 LoadTimeWeaverAware bean 以允许尽早注册它们的转换器.
    		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    		for (String weaverAwareName : weaverAwareNames) {
    			getBean(weaverAwareName);
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    设置参数

    		// 禁止使用临时类加载器进行类型匹配.
    		beanFactory.setTempClassLoader(null);
    		//  允许缓存所有的bean的定义数据.
    		beanFactory.freezeConfiguration();
    
    • 1
    • 2
    • 3
    • 4

    实例化所有剩余的(非延迟初始化)单例

    beanFactory.preInstantiateSingletons();
    
    • 1

    preInstantiateSingletons

    1. 先获取所有的beanName
    // 获取所有bean的名字
    // beanDefinitionNames 按注册顺序排列的一个 beanDefinition集合
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    
    • 1
    • 2
    • 3
    1. 循环 实例化非懒加载的 bean
      1. getMergedLocalBeanDefinition
        初始化时,使用的统一视图是RootBeanDefinition,这里可以看到spring对于具有继承关系的Bean的处理方式——首先初始化父BeanDefinition,
        接着将子BeanDefinition的内容覆盖父BeanDefinition的内容
      2. isFactoryBean(beanName)
        如果 bean 是 factoryBean,先获取 &+ beanName 也就是工厂bean
        之后 根据 isEagerInit 判断是否要初始化 factoryBean要生产的bean
      3. ! isFactoryBean(beanName)
        直接执行getBean
    						FactoryBean<?> factory = (FactoryBean<?>) bean;
    						boolean isEagerInit;
    						    // 获取系统范围的安全管理器                 // 实现SmartFactoryBean可以指示它们是否总是返回独立实例
    						// 如果工厂类继承了SmartFactoryBean,并且isEagerInit()返回True,则在初始化工厂类之后,立刻初始化产品类
    						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
    							isEagerInit = AccessController.doPrivileged(
    									(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
    									getAccessControlContext());
    						}
    						else {
    							isEagerInit = (factory instanceof SmartFactoryBean &&
    									((SmartFactoryBean<?>) factory).isEagerInit());
    						}
    						if (isEagerInit) {
    							// 注意到这里没有&符号,代表初始化产品类
    							getBean(beanName);
    						}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    1. 在初始化Bean之后,若Bean继承了SmartInitializingSingleton,则调用相应的生命周期回调
    for (String beanName : beanNames) {
    			Object singletonInstance = getSingleton(beanName);
    			// SmartInitializingSingleton 单例预实例化阶段结束时触发的回调接口
    			if (singletonInstance instanceof SmartInitializingSingleton) {
    				StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
    						.tag("beanName", beanName);
    				// 类型转换
    				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
    				if (System.getSecurityManager() != null) {
    					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    						smartSingleton.afterSingletonsInstantiated();
    						return null;
    					}, getAccessControlContext());
    				}
    				else {
    					smartSingleton.afterSingletonsInstantiated();
    				}
    				smartInitialize.end();
    			}
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    getBean

    getBean 内部调用 doGetBean

    	return doGetBean(name, null, null, false);
    
    • 1

    doGetBean

    1. 获取规范名称
      返回 bean 名称,必要时去除工厂取消引用前缀,并将别名解析为规范名称。
    	tring beanName = transformedBeanName(name);
    
    • 1
    1. 检查缓存中是否有该bean
    Object sharedInstance = getSingleton(beanName);
    
    • 1

    通过三级缓存查找解决了 单例非懒加载的bean的循环依赖问题
    关于循环依赖的问题可以点击这里

    //  一级缓存 进行查找
    		Object singletonObject = this.singletonObjects.get(beanName);
    										// 判断是否在创建过程中
    		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    			// 二级缓存中获取bean
    			singletonObject = this.earlySingletonObjects.get(beanName);
    
    			// 二级缓存没有获取到       允许早期引用
    			if (singletonObject == null && allowEarlyReference) {
    				synchronized (this.singletonObjects) {
    					//  一级缓存查找
    					singletonObject = this.singletonObjects.get(beanName);
    					if (singletonObject == null) {
    						// 二级缓存查找
    						singletonObject = this.earlySingletonObjects.get(beanName);
    						if (singletonObject == null) {
    							// 三级缓存 获取到 objectFactory 的 getEarlyBeanReference 方法
    							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
    							if (singletonFactory != null) {
    								                         // 这里的getObject 实际上调用的是 getEarlyBeanReference  取到的是循环依赖的半成品对象
    								singletonObject = singletonFactory.getObject();
    								// 二级缓存 放入 bean
    								this.earlySingletonObjects.put(beanName, singletonObject);
    								// 三级缓存清除数据
    								this.singletonFactories.remove(beanName);
    							}
    						}
    					}
    				}
    			}
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    1. 检查缓存中是否有该bean
      1. 缓存中找到该bean
        使用 getObjectForBeanInstance 完成的是FactoryBean的相关处理,已取得FactoryBean的生产结果。
        beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);

      2. 缓存中没有找到该bean
        1.对Ioc 容器中的 BeanDefition 是否存在进行检查,检查是否能在当前的BeanFactory中获取到Bean,如果在当前工厂中取不到,则到双亲BeanFactory中去取,如果双亲中娶不到,那就顺着双亲beanFactory链一直向上寻找
        2. 判断调用getBean()是否仅仅是为了类型检查获取bean,如果是为了创建bean,则先清除掉合并BeanDefinition的标记(使之重新合并)
        3. // 获取 合并之后的 bean定义
        RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
        4. 获取该bean所有依赖的 bean
        5. 创建bean实例. (这里区分了是否为 Singleton , Prototype) 这里使用了函数式编程

    if (mbd.isSingleton()) {
    	//  函数式编程    ObjectFactory singletonFactory  。getObject() 方法
    	sharedInstance = getSingleton(beanName, () -> {
    		try {
    			// 创建bean对象
    			return createBean(beanName, mbd, args);
    		}
    		catch (BeansException ex) {
    			destroySingleton(beanName);
    			throw ex;
    			}
    		});
    beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    				}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1. 最后 对创建的bean 进行类型检查,如果没有问题,就返回这个新创建的Bean,这个Bean已经是包含了依赖关系的bean
      adaptBeanInstance(name, beanInstance, requiredType);

    createBean

    创建bean实例

    1. 解析beanName对应的Bean的类型
      Class resolvedClass = resolveBeanClass(mbd, beanName);
      如果resolvedClass存在,并且mdb的beanClass类型不是Class,并且mdb的beanClass不为空(则代表beanClass存的是Class的name),
      则使用mdb深拷贝一个新的RootBeanDefinition副本,并且将解析的Class赋值给拷贝的RootBeanDefinition副本的beanClass属性,该拷贝副本取代mdb用于后续的操作
    2. 如果bean配置了 PostProcessor ,那么返回一个proxy
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      InstantiationAwareBeanPostProcessor 他是bean实例化的处理器 通常用于抑制特定目标bean的默认实例化
    3. 调用 doCreateBean(beanName, mbdToUse, args) 创建bean

    doCreateBean

    1. 声明一个 BeanWrapper 用来持有创建出来的bean 对象, (其实也是一个策略模式,因为他包含了反射相关算法)
    2. 如果是单例的,先把缓存中同名的bean清除
    3. createBeanInstance() 创建bean实例
    4. 获取 bean对象
    5. MergedBeanDefinitionPostProcessor 处理 ,在bean初始化的时候来提前收集到这些标记了@Value的字段或者方法
    6. 放入三级缓存中
    7. 属性填充
    8. 执行 initializeBean() 初始化bean
    9. 检查是否是一个完整的对象
    10. 注册销毁方法
  • 相关阅读:
    阿维塔30亿元融资背后:价格战再席卷,如何守住品牌底线?
    暑期结束为你的新学期立下Flag吧
    QML-编辑框的使用
    数据结构和算法——用C语言实现所有树形结构及相关算法
    Java面向对象程序设计综合练习1(编程题)
    在uniapp中,如何去掉一些不想要的权限,
    LLM应用实战:当KBQA集成LLM(二)
    腾讯云GPU云服务器计算型GN7有哪些特点?适用于哪些场景?
    体育场馆预约小程序,体育馆预约小程序,体育馆预约系统小程序
    在游戏博弈中才是博弈游戏的最佳实践
  • 原文地址:https://blog.csdn.net/qq_44808472/article/details/126195048