总结:Spring boot启动原理

 一、核心启动源码之initialize

1、整体代码

如下会new SpringApplication对象,这个操作会调用初始化方法,

@SuppressWarnings({ "unchecked", "rawtypes" })
private void initialize(Object[] sources) {
	//sources即我们的启动文件,如Starter.java
	if (sources != null && sources.length > 0) {
		this.sources.addAll(Arrays.asList(sources));
	}
	
	//确定是否是webEnvironment,后续会根据是否是web环境进行一些操作,如上下文初始化实例的选择(createApplicationContext)
	this.webEnvironment = deduceWebEnvironment();
	
	//上下文初始化:使用内部工具类SpringFactoriesLoader从META-INF/spring.factories加载加载所有ApplicationContextInitializer实现类并实例化,
	//并将这些实例设置到SpringApplication的List<ApplicationContextInitializer<?>> initializers中
	//初始化实例包含:
	setInitializers((Collection) getSpringFactoriesInstances(
			ApplicationContextInitializer.class));
			
	//监听实例初始化:从META-INF/spring.factories加载实现了ApplicationListener接口的类并生成实例对象,
	//并将这些实例设置到SpringApplication的private List<ApplicationListener<?>> listeners中
	setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
	
	//获取main函数所在的类
	this.mainApplicationClass = deduceMainApplicationClass();
}

2、springboot - web环境的推断

SpringApplication会尝试帮你创建正确的ApplicationContext,默认情况下会使用AnnotationConfigApplicationContext或者 AnnotationConfigEmbeddedWebApplicationContext,这取决于你开发的是否是web环境。判断Web environment算法是非常简单的,直接基于某些类的存在与否。

如下:直接判断类路径下是否存在"javax.servlet.Servlet","org.springframework.web.context.ConfigurableWebApplicationContext"两个类即可。

3、上下文初始化

上下文实例详解:

//缺省 Web SpringApplication 应用会有以下 6 个 ApplicationContextInitializer: 
//1.初始化任务委托给Environment指定的初始化器,
//相当于给外界提供了一个添加自定义ApplicationContextInitializer的入口
//委托给Environment属性context.initializer.classes下指定的ApplicationContextInitializer类,
DelegatingApplicationContextInitializer

//2.设置Spring ApplicationContext ID
//这些环境变量会被用来产生Spring ApplicationContext ID : 
// spring.application.name,vcap.application.name,spring.config.name
// 如果没有找到以上属性设置,ID使用 application
ContextIdApplicationContextInitializer

//3.用于报告一般配置错误,
//添加BeanFactoryPostProcessor : ConfigurationWarningsPostProcessor
ConfigurationWarningsApplicationContextInitializer 

//4.添加 ApplicationListener<EmbeddedServletContainerInitializedEvent>
ServerPortInfoApplicationContextInitializer

//5.在ConfigurationClassPostProcessor和Spring boot之间增加一个共享的CachingMetadataReaderFactory
//添加BeanFactoryPostProcessor : CachingMetadataReaderFactoryPostProcessor
SharedMetadataReaderFactoryContextInitializer

//6.将ConditionEvaluationReport写到log,在DEBUG级别下输出
//添加AutoConfigurationReportListener
AutoConfigurationReportLoggingInitializer

4、监听初始化

二、核心启动源码之run方法

1、整体代码

public ConfigurableApplicationContext run(String... args) {
		//创建计时器
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		
		// 声明 IOC 容器
		ConfigurableApplicationContext context = null;
		FailureAnalyzers analyzers = null;
		
		//作用:即使没有检测到显示器,也允许其启动。对于服务器来说,是不需要显示器的,所以要这样设置
		configureHeadlessProperty();
		
		//准备运行时监听器EventPublishingRunListener,方式为从类路径下找到 META/INF/Spring.factories 获取 SpringApplicationRunListeners
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
			
			// 封装命令行参数,也就是在命令行下启动应用带的参数,如--server.port=9000 
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
					
			// 准备环境,1、加载外部化配置的资源到environment;2、触发ApplicationEnvironmentPreparedEvent事件,
			//创建环境完成后回调 SpringApplicationRunListeners#environmentPrepared()方法,表示环境准备完成 
			// 环境准备的主要工作就是 将系统属性配置及用户定义的属性配置 加载进来
			ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);
			
			// 打印banner图。banner即下面这坨东西,可以设置关掉打印,也可以修改
						.   ____          _            __ _ _
			 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
			( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
			 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
			  '  |____| .__|_| |_|_| |_\__, | / / / /
			 =========|_|==============|___/=/_/_/_/
			 :: Spring Boot ::        (v1.5.6.RELEASE)
			 
			Banner printedBanner = printBanner(environment);
			
			//创建应用上下文,决定创建web的ioc还是普通的ioc
			context = createApplicationContext();
			
			//容器启动失败分析,如端口被占用等
			analyzers = new FailureAnalyzers(context);
			
			//做context的准备工作,如把相关需要创建bean的类加载到上下文中
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			
			//刷新上下文,
            //很重要的就包含对上面被加载的bean进行实例化
            //另外,@EnableAutoConfiguration相关配置也在这里将需要装配的bean给装配好
			refreshContext(context);
			
			//刷新Context容器之后处理
			afterRefresh(context, applicationArguments);

            //通过EventPublishingRunListener发布finished事件
			listeners.finished(context, null);

			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass)
						.logStarted(getApplicationLog(), stopWatch);
			}
			return context;
		}
		catch (Throwable ex) {
			handleRunFailure(context, listeners, analyzers, ex);
			throw new IllegalStateException(ex);
		}
	}

2、SpringApplicationRunListeners

SpringApplicationRunListener 的作用是在SpringApplication 的各个启动过程中,监听各个阶段的变化,并将每个阶段封装成事件(ApplicationEvent),发布出去。让其他监听这些事件的监听器能探测到,并调用到对应的处理方法。

1. SpringApplicationRunListener 是一个接口,它的主要实现类是 EventPublishingRunListener 类。主要作用是监听 SpringApplication 启动的各个阶段,并封装成对应的 ApplicationEvent ,并把它发布出去。

2. 这里运用到一个观察者模式,不懂的小朋友可以多百度一下。

3. 我们可以定义自己的SpringApplicationRunListener, 实现这个接口,然后再新建一个 META-INF/spring.factorie 文件,注册监听即可。

3、SpringApplicationRunListeners与ApplicationListener的区别

SpringApplicationRunListeners负责在SpringBoot启动的不同阶段, 广播出不同的消息, 传递给ApplicationListener监听器实现类。

SpringApplicationRunListeners从Java监听器的角度看,并不是一个监听器,只是个普通的Java类而已,可以去看这个类的定义。

而ApplicationListener是传统意义上的Java监听器,如实现类DelegatingApplicationListener, 实现了ApplicationListener,ApplicationListener继承了EventListener。

4、ApplicationContextInitializer

用来在对ApplicationContext进行refresh操作之前对Application context进行一些初始化操作。

主要用来在ConfigurableApplicationContext#refresh()之前对ConfigurableApplicationContext进行一些初始化的操作。一般来说主要做一些程序化的操作,比如注册配置源,根据配置激活某个profile等

5、ApplicationListener

基于观察者模式的Application的事件监听器。将ApplicationListener注册到ApplicationContext中,当有对应事件发生时,监听器会被调用。

ApplicationContextInitializerApplicationListener的加载是在类SpringApplication的构造函数中完成的,具体都是通过调用函数getSpringFactoriesInstances(Class<T> type)来完成的。

在spring boot中默认配置的ApplicationListener还挺多的,我们就摘抄几个比较重要的分析一下。

ConfigFileApplicationListener

ConfigFileApplicationListener是一个非常重要的监听器,除了是一个监听器之外,它实现了接口EnvironmentPostProcessor。在监听到事件时,会从指定的文件加载配置并配置application context。

可以看到继承实现了接口EnvironmentPostProcessor的方法postProcessEnvironment,负责对SpringApplication的Environment进行处理。具体实现上可以看到创建了一个Loader,这个Loader会负责去javadoc描述得地方去查找文件并加载配置。

public class ConfigFileApplicationListener
		implements EnvironmentPostProcessor, SmartApplicationListener, Ordered {
    private void onApplicationEnvironmentPreparedEvent(
    		ApplicationEnvironmentPreparedEvent event) {
    	List<EnvironmentPostProcessor> postProcessors = loadPostProcessors();
    	postProcessors.add(this);
    	AnnotationAwareOrderComparator.sort(postProcessors);
    	for (EnvironmentPostProcessor postProcessor : postProcessors) {
    		postProcessor.postProcessEnvironment(event.getEnvironment(),
    				event.getSpringApplication());
    	}
    }
    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment,
    		SpringApplication application) {
    	addPropertySources(environment, application.getResourceLoader());
    }
    protected void addPropertySources(ConfigurableEnvironment environment,
    		ResourceLoader resourceLoader) {
    	RandomValuePropertySource.addToEnvironment(environment);
    	new Loader(environment, resourceLoader).load();
    }
}

重点看一下方法onApplicationEnvironmentPreparedEvent。在监听到ApplicationEnvironmentPreparedEvent事件之后,除了将自己加入到List<EnvironmentPostProcessor>之外,还会调用函数loadPostProcessors去加载在文件META-INF/spring.factories配置的EnvironmentPostProcessor,最后执行所有的postProcessEnvironment方法。


三、EnableAutoConfiguration

@EnableAutoConfiguration结合spring.factories实现了对外部依赖包的扫描。

具体参考我的另一篇博客:总结:Spring boot之@EnableAutoConfiguration

参考:

总结:Spring Boot 之spring.factories

Spring Boot创建Beans的过程分析

Springboot Feign整合源码解析

Spring Boot 中 @EnableXXX 注解的驱动逻辑

Spring Boot启动过程分析

SpringApplicationRunListener 是干啥的?

spring-boot-2.0.3不一样系列之源码篇 - run方法(三)之createApplicationContext,绝对有值得你看的地方

SpringApplication 的初始化过程分析 : initialize()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot启动原理可以分为以下几个步骤: 1. 加载并解析Spring Boot的配置文件:Spring Boot会首先加载并解析classpath下的application.properties或application.yml文件,将其中的配置项解析为Spring Boot内部的配置属性。 2. 创建并启动Spring应用上下文:Spring Boot会创建一个Spring应用上下文,加载应用中的所有bean,并为它们自动配置所需的依赖关系。Spring Boot提供了很多自动配置的starter模块,可以根据应用所需的功能,自动配置相关的bean和依赖。 3. 执行Spring Boot的自动配置:Spring Boot会根据classpath中的jar包和配置文件中的属性,自动配置应用所需的bean和依赖关系。这些自动配置是通过Spring Boot的条件注解实现的,只有在满足特定条件的情况下才会被执行。 4. 启动Spring MVC:如果应用中包含Spring MVC相关的jar包,Spring Boot会自动配置并启动Spring MVC框架,同时会自动配置一些常用的MVC组件,如ViewResolver、HandlerMapping等。 5. 启动内嵌的Web服务器:Spring Boot支持内嵌的Web服务器,如Tomcat、Jetty等。在启动Spring Boot应用时,会根据配置文件中的属性,自动配置并启动内嵌的Web服务器,同时将Spring应用上下文注册到Web服务器中。 总的来说,Spring Boot启动原理是通过自动化配置和条件注解,根据应用所需的功能,自动配置相关的bean和依赖关系,并启动内嵌的Web服务器。这种方式可以大大简化应用的开发和部署,提高开发效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值