SpringBoot启动流程

SpringBoot启动过程

  • 生成一个SpringApplication对象
    • webApplicationType(推断web应用类型,NONE、REACTIVE、SERVLET)
    • 从spring.factories中获取BootstrapRegistryInitializer对象
    • initializers = 从spring.factories中获取ApplicationContextInitializer对象
    • listeners = 从spring.factories中获取ApplicationListener对象
  • SpringApplication对象的Run方法
    • 获取SpringApplicationRunListener--->EventPublishingRunListener
    • SpringApplicationRunListener.starting() 容器处理开始创建状态
    • 创建一个Spring容器
    • ApplicationContextInitializer--->初始化Spring容器
    • SpringApplicationRunListener.contextPrepared()
    • 把传给run方法的配置类注册成为一个Bean
    • SpringApplicationRunListenner.contextLoaded()
    • 会解析配置类、扫描、启动tomcat/jetty
    • SpringApplicationRunListener.started()
    • SpringApplicationRunListener.ready()

  • run方法启动时传入了当前类 ContractApplication.class,传入当前类的作用主要是为了解析当前类上面的注解(不一定传递当前类,也可以自己写一个类,在写的类上添加对应的注解)
@SpringBootApplication
@ComponentScan("com.example")
public class ContractApplication {
    public static void main(String[] args) {
        SpringApplication.run(ContractApplication.class);
    }
}
  • 将传入的类封装成一个Class类型的数组
    public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
        return run(new Class[]{primarySource}, args);
    }
  • 生成一个SpringApplication对象,在调用SpringApplication的run方法
    public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
        return (new SpringApplication(primarySources)).run(args);
    }
  • new SpringApplication()构造方法,主要是给SpringApplication对象中的属性赋值
	public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        //资源加载器
		this.resourceLoader = resourceLoader;
        //判断传进来的类是否为空
		Assert.notNull(primarySources, "PrimarySources must not be null");
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
        //1.推测项目的应用类型(通过项目目录结构,和类),NONE(不是Web项目),REACTIVE(Web应用,响应式),SERVLET(Web应用,springmvc)
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
        //2.从spring.factories中获取需要加载的BootstrapRegistryInitializer类型的的实现类
		this.bootstrapRegistryInitializers = new ArrayList<>(
				getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
        //3.从spring.factories中获取需要加载的AppliationContextInitializer(初始化器)类型的实现类
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
        //4.从spring.factories中获取需要加载的ApplicationListener(应用监听器)类型的实现类
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        //5.推测出Main类(main()方法所在的类)
		this.mainApplicationClass = deduceMainApplicationClass();
	}
  • spring.factories
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer
  • SpringApplication.run()
	public ConfigurableApplicationContext run(String... args) {
        //记录开始启动的时间
		long startTime = System.nanoTime();

		DefaultBootstrapContext bootstrapContext = createBootstrapContext();
        //定义了一个Spring容器
		ConfigurableApplicationContext context = null;
		configureHeadlessProperty();

        //从spring.factories中获取SpringApplicationRunListener对象
        //默认会拿到一个EventPublishingRunListener,它会启动过程的各个阶段发布对应的事件(运行监听器)
		SpringApplicationRunListeners listeners = getRunListeners(args);
        //执行RunListener的start方法
		listeners.starting(bootstrapContext, this.mainApplicationClass);
		try {
            //将run()的参数封装为DefaultApplicatoinArguments对象
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            //配置环境,properties文件的配置,setvlet,jvm环境配置等,封装成ConfigurableEnvironment
			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
			configureIgnoreBeanInfo(environment);
            //打印spirngboot启动banner
			Banner printedBanner = printBanner(environment);
            //根据应用类型创建Spring容器
			context = createApplicationContext();
			context.setApplicationStartup(this.applicationStartup);
            //使用初始化器初始化Spring容器
			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
            //刷新Spring容器,会解析配置类,扫描 启动WebServer
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
			}
            //spring容器状态为started
			listeners.started(context, timeTakenToStartup);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, listeners);
			throw new IllegalStateException(ex);
		}
		try {
			Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
            //spring容器状态为ready
			listeners.ready(context, timeTakenToReady);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

自动配置原理

  • @SpringApplication

    • @EnableAutoConfiguration
      • @Import(AutoConfigurationImportSelector.class)

  • AutoConfigurationImportSelector.java

	public String[] selectImports(AnnotationMetadata annotationMetadata) {
        //会在所有@Configuration都解析完了之后才执行
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
				.loadMetadata(this.beanClassLoader);
        //获取自动配置类(spirng.factories中导入)
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
				annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}
  • getAutoConfigurationEntry()
	protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
			AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
        //获取@EnableAutoConfiguration的属性
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
        //获取spring.factories中所有的AutoConfiguration
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
        //去重
		configurations = removeDuplicates(configurations);
        //获取需要排除的AutoConfiguration  @EnableAutoConfiguation注解的exclude属性设置
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		checkExcludedClasses(configurations, exclusions);
		configurations.removeAll(exclusions);
        //过滤
		configurations = filter(configurations, autoConfigurationMetadata);
		fireAutoConfigurationImportEvents(configurations, exclusions);
        //最后返回的AutoConfiguration都是符合条件的
		return new AutoConfigurationEntry(configurations, exclusions);
	}
posted @ 2022-12-01 10:39  youmo~  阅读(68)  评论(0编辑  收藏  举报