本文分析SpringBoot启动类及其原理主要是从一下俩个方面来分析的

  1.  解析@SpringBootApplication
  2. 解析run方法

解析@SpringBootApplication

@SpringBootConfiguration

首先这是一个配置类,继承于@Configuration,本身只是说明这是一个SpringBoot项目的配置类,功能与@Configuration一样,使得Spring容器知道需要跟处理@Configuration注解的类一样处理这个类。

@EnableAutoConfiguration

故名思意这是一个自动装配

 一是收集所有spring.factories中EnableAutoConfiguration相关bean的类,初始化为一个相关的bean;

        二是将得到的类注册到spring容器中,启动自动化置。 总的来说@EnableAutoConfiguration是借助@Import的帮助,将所有符合自动配置条件的bean定义加载到IoC容器,

@ComponetScan

这是一个基于注解的类扫描

用于进行包扫描,检查类是否使用了@Controller,@Service等注解,有则获取这些类创建对应的bean对象注册到Spring容器。

 

解析run方法

在解析run方法之前,我们需要了解SpringApplication类主要做了哪四件事情。

根据启动类中SpringApplication的源码中的构造函数我们可以得知

//先把主类保存起来
        this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
        //1、判断运行项目的类型
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        //2、扫描当前路径下META-INF/spring.factories文件的,加载ApplicationContextInitializer            
        //接口实例
        
        setInitializers((Collection)              
                       getSpringFactoriesInstances(ApplicationContextInitializer.class)); 
        //3、扫描当前路径下META-INF/spring.factories文件的,加载ApplicationListener接口实例
        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        //4、判断并设置main方法的定义类,找到运行的主类
        this.mainApplicationClass = deduceMainApplicationClass();

接下来我们来正式解析run方法

下面是一个application运行的时序图

  

spring boot 修改启动类名称 springboot设置启动类_spring boot 修改启动类名称

 

 

接下来我们来看看 ConfigurableApplicationContext  new出来的run的源码

public ConfigurableApplicationContext run(String... args) {
    
        // 1、这个是一个计时器
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
            
        //2、设置了一些环境变量 
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
        configureHeadlessProperty();
 
 
        //3、获取事件监听器SpringApplicationRunListener类型,并且执行starting()方法
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
 
		try {
 
 
            //4、把参数args封装成DefaultApplicationArguments
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);
 
            //5、这个很重要准备环境了,并且把环境跟spring上下文绑定好,并且执行            
            //environmentPrepared()方法
			ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);
 
            //6、判断一些环境的值,并设置一些环境的值
			configureIgnoreBeanInfo(environment);
 
            //7、打印banner
			Banner printedBanner = printBanner(environment);
 
 
            //8、创建上下文,根据项目类型创建上下文
			context = createApplicationContext();
 
 
            //9、获取异常报告事件监听
			exceptionReporters = getSpringFactoriesInstances(
					SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
 
 
            //10、准备上下文,执行完成后调用contextPrepared()方法,contextLoaded()方法
			prepareContext(context, environment, listeners, applicationArguments,
					printedBanner);
 
 
           //11、这个是spring启动的代码了,这里就回去里面就回去扫描并且初始化单实列bean了
           //这个refreshContext()加载了bean,还启动了内置web容器
	       //最核心的一步,将之前通过@EnableAutoConfiguration获取的所有配置以及其他形式的IoC容 
           //器配置加载到已经准备完毕的ApplicationContext。

			refreshContext(context);
 
         
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass)
						.logStarted(getApplicationLog(), stopWatch);
			}
 
    
            //12、执行ApplicationRunListeners中的started()方法
			listeners.started(context);
 
            //13、执行Runner(ApplicationRunner和CommandLineRunner)
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, listeners, exceptionReporters, ex);
			throw new IllegalStateException(ex);
		}
		listeners.running(context);
		return context;
	}

为了方便理解源码我们可以看一下一下的run方法的分析图。

spring boot 修改启动类名称 springboot设置启动类_初始化_02

 

 

到此关于SpringBoot启动类及其原理的简单分析就已经完成了。再此感谢吴同学提供的素材。