springboot启动流程梳理

创建SpringApplication对象

1.启动类中会调用SpringApplication中的静态run方法创建SpringApplication对象
,并调用SpringApplication的run方法

   public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
        return (new SpringApplication(primarySources)).run(args);
    }

2.创建SpringApplication对象

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		//保存主启动类到set集合中,可以是多个
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		/** 判断Application类型,后续会根据该参数选择ApplicationContext容器,主要有三种
		*1.NONE:作为非web应用启动
		*2.SERVLET:基于servlet的web应用
		*3.REACTIVE: 作为一个reactive的web应用
		*/
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		//加载并创建springfactories文件中BootstrapRegistryInitializer的所有实现类的实例对象
		this.bootstrapRegistryInitializers = new ArrayList<>(getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
		//加载springfactories文件中的所有实现类,并放入到缓存中。后续加载直接从缓存中读取
		//返回springfactories文件中ApplicationContextInitializer所有实现类对象
setInitializers((Collection)getSpringFactoriesInstances(ApplicationContextInitializer.class));
		//加载springfactories文件中ApplicationListener所有实现类
setListeners((Collection)getSpringFactoriesInstances(ApplicationListener.class));
		//得到根据main方法得到主类
		this.mainApplicationClass = deduceMainApplicationClass();
	}

环境准备

SpringBootExceptionReporter 异常分析器

使用java的spi机制,从springfactories文件中获取实现类(因为前面已经将其放入缓存中,所以可以直接从缓存中获取)。SpringBootExceptionReporter接口对应实现类FailureAnalyzers

private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
        Map<String, List<String>> result = (Map)cache.get(classLoader);
        if (result != null) {
            return result;
        } else {

初始化FailureAnalyzers时,会先将FailureAnalyzer的所有继承类从缓存中读取,同样使用了java的spi机制。

	FailureAnalyzers(ConfigurableApplicationContext context) {
		this(context, SpringFactoriesLoader.loadFactoryNames(FailureAnalyzer.class, getClassLoader(context)));
	}

之后再将初始化完成的所有异常分析器(FailureAnalyzer的所有继承类)放入FailureAnalyzer成员变量中。同时判断所有异常分析器是否实现BeanFactoryAware,EnvironmentAware接口。如果实现了则将当前容器中的beanFactory,environment放入异常分析器中。因为万一在BeanFactory,Environment织入之前springboot启动报错的话,异常分析器会得不到容器的beanFactory,environment对象。

	private List<FailureAnalyzer> handleAwareAnalyzers(List<FailureAnalyzer> analyzers,
			ConfigurableApplicationContext context) {
		List<FailureAnalyzer> awareAnalyzers = analyzers.stream()
			.filter((analyzer) -> analyzer instanceof BeanFactoryAware || analyzer instanceof EnvironmentAware)
			.collect(Collectors.toList());
		if (!awareAnalyzers.isEmpty()) {
			String awareAnalyzerNames = StringUtils.collectionToCommaDelimitedString(awareAnalyzers.stream()
				.map((analyzer) -> analyzer.getClass().getName())
				.collect(Collectors.toList()));
			logger.warn(LogMessage.format(
					"FailureAnalyzers [%s] implement BeanFactoryAware or EnvironmentAware. "
							+ "Support for these interfaces on FailureAnalyzers is deprecated, "
							+ "and will be removed in a future release. "
							+ "Instead provide a constructor that accepts BeanFactory or Environment parameters.",
					awareAnalyzerNames));
			if (context == null) {
				logger.trace(LogMessage.format("Skipping [%s] due to missing context", awareAnalyzerNames));
				return analyzers.stream()
					.filter((analyzer) -> !awareAnalyzers.contains(analyzer))
					.collect(Collectors.toList());
			}
			awareAnalyzers.forEach((analyzer) -> {
				if (analyzer instanceof BeanFactoryAware) {
					((BeanFactoryAware) analyzer).setBeanFactory(context.getBeanFactory());
				}
				if (analyzer instanceof EnvironmentAware) {
					((EnvironmentAware) analyzer).setEnvironment(context.getEnvironment());
				}
			});
		}
		return analyzers;
	}

最后根据捕获到的springboot启动的异常得到对应的异常分析器。再从缓存中取出FailureAnalysisReporter进行异常汇报

	@Override
	public boolean reportException(Throwable failure) {
		FailureAnalysis analysis = analyze(failure, this.analyzers);
		return report(analysis, this.classLoader);
	}

	private boolean report(FailureAnalysis analysis, ClassLoader classLoader) {
		List<FailureAnalysisReporter> reporters = SpringFactoriesLoader.loadFactories(FailureAnalysisReporter.class,
				classLoader);
		if (analysis == null || reporters.isEmpty()) {
			return false;
		}
		for (FailureAnalysisReporter reporter : reporters) {
			reporter.report(analysis);
		}
		return true;
	}

environment 系统环境

在springboot启动流程中,调用以下方法初始化environment。将不同的环境信息封装到不同的propertySources中。并按顺序排序,如果不同的propertySource中有相同的配置,则按照排序顺序取值。

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
		// 初始化environment对象,同时在父类的构造函数中读取操作系统变量(env)以及应用环境变量(propertis)
		// 如果是servlet应用还会读取servletConfigInitParams变量以及servletContextInitParams变量
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		//读取启动参数到environment中
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		//读取configurationProperty配置,并放到第一位。
		ConfigurationPropertySources.attach(environment);
		//使用SpringApplicationRunListener监听器发布environment事件。
		//EnvironmentPostProcessorApplicationListener监听environment事件
		//拿到EnvironmentPostProcessor所有的实现类。并执行增强方法。
		//该步骤主要能得到bootStrap.yml文件和application.yml文件的配置信息
		//后续不同环境的application.yml文件以及apollo配置信息在BeanFactoryPostProcessor对容器进行增强时读取
		listeners.environmentPrepared(bootstrapContext, environment);
		DefaultPropertiesPropertySource.moveToEnd(environment);
		Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
				"Environment prefix cannot be set via properties.");
		bindToSpringApplication(environment);
		if (!this.isCustomEnvironment) {
			EnvironmentConverter environmentConverter = new EnvironmentConverter(getClassLoader());
			environment = environmentConverter.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
		}
		ConfigurationPropertySources.attach(environment);
		return environment;
	}

SpringApplicationRunListener 运行时监听器

通过spi机制读取springfactories文件中获取SpringApplicationRunListener的实现类,并存入SpringApplicationRunListeners中。当springboot启动时即可通过SpringApplicationRunListeners中调用所有监听器处理事件。springboot中自带了一个监听器EventPublishingRunListener,将对应事件广播给springboot的监听器处理。environment准备时也是通过该种方式实现。SpringApplicationRunListener中主要有以下几个事件。

//springboot开始启动
default void starting(ConfigurableBootstrapContext bootstrapContext) {
	}

//准备environment
default void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,
			ConfigurableEnvironment environment) {
	}

//准备context
	default void contextPrepared(ConfigurableApplicationContext context) {
	}

//加载context
	default void contextLoaded(ConfigurableApplicationContext context) {
	}
//context刷新并启动完成
	default void started(ConfigurableApplicationContext context, Duration timeTaken) {
		started(context);
	}

//CommandLineRunner和ApplicationRunner已经执行
	default void ready(ConfigurableApplicationContext context, Duration timeTaken) {
		running(context);
	}

//springboot启动失败
	default void failed(ConfigurableApplicationContext context, Throwable exception) {
	}

创建、初始化、刷新 ApplicationContex容器

待续

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值