SpringBoot源码分析-启动流程、解决循环依赖

1、启动流程:

 

SpringApplication.run(BootWebApplication.class, args);

 

SpringApplication类public ConfigurableApplicationContext run(String... args) 核心方法:
  public ConfigurableApplicationContext run(String... args) {
        //计时器
        StopWatch stopWatch = new StopWatch();
        // 记录当前服务开始启动
        stopWatch.start();
        // 上下文context,非常关键
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
        // 给系统设置headless属性值
        configureHeadlessProperty();
        //listeners
        // 就是通过SpringFactoriesLoader 获取到所有SpringApplicationRunListener.class的对象
        // 其中args是用来进行实例化SpringApplicationRunListener对应的对象的构造器参数
        // 最后返回listener是整个系统的监听器
        SpringApplicationRunListeners listeners = getRunListeners(args);
        listeners.starting();
        try {
            // 默认程序参数
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            //environment 
            // 准备运行的环境上下文
            ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
            configureIgnoreBeanInfo(environment);
            // 打印banner,默认输出当前springboot版本等内容,可以自定义设置文本或者图片
            // 具体看下面的方法详解
            Banner printedBanner = printBanner(environment);
            // 创建SpringBoot最重要的上下文容器
            context = createApplicationContext();

			/*SpringFactoriesLoader.loadFactoryNames(type, classLoader)SpringBoot框架中从类路径jar包中读取特定文件实现扩展类的载入
			将所有Jar中的spring.factories(A.jar(spring.factories)*/
            //使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationContextInitializer。
使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationListener。
            exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                    new Class[]{ConfigurableApplicationContext.class}, context);
            // 看名称就是对context的前置准备工作,细节在后面说
            prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            // 核心方法 创建注册Bean 一级二级三级缓存 依赖注入
            // 切入到spring framework的方式去完成context内容的装载
            // 如果需要注册终止钩子,则注册一个
            refreshContext(context);
            //初始化接口 ApplicationRunner/CommandLineRunner
            // 基本上认为springboot所需的服务都加载完成,进行最后的处理操作
            afterRefresh(context, applicationArguments);
            //表示SpringBoot服务启动步骤完成,统计下启动时间等操作

            stopWatch.stop();
            if (this.logStartupInfo) {
                // 打印SpringBoot启动成功的消息,例如 Started xxx in 12.4 seconds 等信息
                new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
            }
            //监听器正式启动
            listeners.started(context);
            //初始化实现的接口启动
            callRunners(context, applicationArguments);
        } catch (Throwable ex) {
            // 启动失败了就会输出Application startup failed 日志
            // 并且会输出具体的错误内容信息
            handleRunFailure(context, ex, exceptionReporters, listeners);

        }throw new IllegalStateException(ex);
		}

2、解决依赖注入

refreshContext(context);
applicationContext.refresh();
AbstractApplicationContext:
refresh();

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}
仅对于单例而言解决循环依赖:
DefaultSingletonBeanRegistry类:
singletonObjects对应一级缓存,earlySingletonObjects对应二级缓存,singletonFactories对应三级缓存。

调用applicationContext.getBean(xx)方法,最终会调到AbstractBeanFactory类的doGetBean方法;

	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;

上面getSingleton方法的逻辑是:

先从singletonObjects(一级缓存)中获取实例,如果可以获取到则直接返回singletonObject实例。
如果从singletonObjects(一级缓存)中获取不对实例,再从earlySingletonObjects(二级缓存)中获取实例,如果可以获取到则直接返回singletonObject实例。
如果从earlySingletonObjects(二级缓存)中获取不对实例,则从singletonFactories(三级缓存)中获取singletonFactory,如果获取到则调用getObject方法创建实例,把创建好的实例放到earlySingletonObjects(二级缓存)中,并且从singletonFactories(三级缓存)删除singletonFactory实例,然后返回singletonObject实例。
如果从singletonObjects、earlySingletonObjects和singletonFactories中都获取不到实例,则singletonObject对象为空。

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值