我是靠谱客的博主 狂野白昼,最近开发中收集的这篇文章主要介绍Spring启动流程源码之finishBeanFactoryInitialization一、finishBeanFactoryInitialization,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

        finishBeanFactoryInitialization是Spring启动中refresh方法里比较重要的最后一步,之前所有的准备和操作都是为了这步操作做的准备,我们直接去看源码分析。

 

一、finishBeanFactoryInitialization

finishBeanFactoryInitialization的源码在org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization下,内容如下:

  protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        //1、类型转换器,不重要
		if (beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {
            beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));
        }
		//2、注册解析器:用于读取配置文件中的内容,例如${},解析成真正的属性
        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver((strVal) -> {
                return this.getEnvironment().resolvePlaceholders(strVal);
            });
        }

		//3、处理 @EnableLoadTimeWeaving 或  <context:load-time-weaver/> 标记的类
		//作用:jvm加载时织入某些类,空的,不重要
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        String[] var3 = weaverAwareNames;
        int var4 = weaverAwareNames.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            String weaverAwareName = var3[var5];
            this.getBean(weaverAwareName);
        }
		
		//4、临时类加载器设置为空
        beanFactory.setTempClassLoader((ClassLoader)null);
		//5、冻结所有的bean,注册的bean定义不会被修改或进一步后处理,因为马上要进行创建bean的操作了
        beanFactory.freezeConfiguration();
		//6、创建bean,重要
        beanFactory.preInstantiateSingletons();
    }

由上面源码可以看出finishBeanFactoryInitialization方法中前面都是仍然是在做一些准备,最最重要的方法依然是在preInstantiateSingletons方法中,那么这个方法又做了哪些事情呢?我们接着往下看:

	public void preInstantiateSingletons() throws BeansException {
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Pre-instantiating singletons in " + this);
        }

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

        while(true) {
            String beanName;
            Object bean;
            do {
                while(true) {
                    RootBeanDefinition bd;
					//注意:以下懒加载、抽象、非singletons是不需要初始化的,因此不会调用getBean
					//判断是否是懒加载
                    do {
						//判断是否不是singletons
                        do {
							//判断是否是抽象
                            do {
                                if (!var2.hasNext()) {
                                    var2 = beanNames.iterator();

                                    while(var2.hasNext()) {
                                        beanName = (String)var2.next();
                                        Object singletonInstance = this.getSingleton(beanName);
										//如果bean实现了 SmartInitializingSingleton 接口,在这里会回调它的afterSingletonsInstantiated方法
                                        if (singletonInstance instanceof SmartInitializingSingleton) {
                                            SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;
                                            if (System.getSecurityManager() != null) {
                                                AccessController.doPrivileged(() -> {
                                                    smartSingleton.afterSingletonsInstantiated();
                                                    return null;
                                                }, this.getAccessControlContext());
                                            } else {
                                                smartSingleton.afterSingletonsInstantiated();
                                            }
                                        }
                                    }

                                    return;
                                }

                                beanName = (String)var2.next();
								//在这一步会先去根据name返回BeanDefinition,然后去处理属性继承和覆盖的关系,获取最终的属性
                                bd = this.getMergedLocalBeanDefinition(beanName);
                            } while(bd.isAbstract());
                        } while(!bd.isSingleton());
                    } while(bd.isLazyInit());
					
					//约定俗成,如果是FactoryBean需要在前面加上'&',再去调用getBean
                    if (this.isFactoryBean(beanName)) {
                        bean = this.getBean("&" + beanName);
                        break;
                    }
					//调用前置后置处理器、实例化、填充、反射,都在这个getBean里!
                    this.getBean(beanName);
                }
            } while(!(bean instanceof FactoryBean));

			//处理FactoryBean
            FactoryBean<?> factory = (FactoryBean)bean;
            boolean isEagerInit;
			//判断当前 FactoryBean 是否是 SmartFactoryBean 的实现,此处忽略,直接跳过
            if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                SmartFactoryBean var10000 = (SmartFactoryBean)factory;
                ((SmartFactoryBean)factory).getClass();
                isEagerInit = (Boolean)AccessController.doPrivileged(var10000::isEagerInit, this.getAccessControlContext());
            } else {
                isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)factory).isEagerInit();
            }

            if (isEagerInit) {
                this.getBean(beanName);
            }
        }
    }

从上面两个源码我们很容易发现,preInstantiateSingletons方法中的主要流程如下:

 至此,Spring启动流程的refresh方法就介绍完了,至于getBean、doGetBean、createBean、doCreateBean这些创建bean的源码解析可以看我的另外一篇文章【Spring】Spring中的三级缓存及循环依赖的问题

最后

以上就是狂野白昼为你收集整理的Spring启动流程源码之finishBeanFactoryInitialization一、finishBeanFactoryInitialization的全部内容,希望文章能够帮你解决Spring启动流程源码之finishBeanFactoryInitialization一、finishBeanFactoryInitialization所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(41)

评论列表共有 0 条评论

立即
投稿
返回
顶部