Spring源码解析----SpringBoot启动流程

一个简单的SB程序如下,点击main方法左边的原谅色的三角形就能把程序启动起来,虽然什么功能都没有,但是启动做了很多处理,加载了很多支持多种功能的组件(类似使用new ClassPathXmlApplicationContext()启动一个Spring程序,其中加载了很多东西)

@SpringBootApplication
public class SpringBootDemoApplication {
   

    public static void main(String[] args) {
   
        SpringApplication.run(SpringBootDemoApplication.class, args);
    }

}

分析的入口就是从SpringApplication的run方法开始,而@SpringBootApplication注解在后续的处理中会用到,所以暂时忽略

1.入口

进入run方法

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

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

2.初始化SpringApplication

首先初始化了SpringApplication,然后再调用其run方法,那么先看下SpringApplication的构造方法里的逻辑

	public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
   
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
        // 即demo里的SpringBootDemoApplication对应的Class对象集合
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
        // 应用的类型,共三种类型
        // reactive、servlet  、非web应用
		this.webApplicationType = deduceWebApplicationType();
        // 获取spring.factories中配置的ApplicationContextInitializer的实现类并实例化,最后放到集合当中
		setInitializers((Collection) getSpringFactoriesInstances(
				ApplicationContextInitializer.class));
        // 原理同上
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        // 找到执行main方法的那个类的Class对象,即demo中的SpringBootDemoApplication对应的Class对象
		this.mainApplicationClass = deduceMainApplicationClass();
	}

2.1获取应用类型

SpringApplication构造方法里,调用了deduceWebApplicationType来判断是什么类型的应用,那么SpringBoot是如何判断的呢?往里进去看下具体实现

	private WebApplicationType deduceWebApplicationType() {
   
        //REACTIVE_WEB_ENVIRONMENT_CLASS = org.springframework.web.reactive.DispatcherHandler
        //MVC_WEB_ENVIRONMENT_CLASS = org.springframework.web.servlet.DispatcherServlet
		if (ClassUtils.isPresent(REACTIVE_WEB_ENVIRONMENT_CLASS, null)
				&& !ClassUtils.isPresent(MVC_WEB_ENVIRONMENT_CLASS, null)) {
   
			return WebApplicationType.REACTIVE;
		}
        //WEB_ENVIRONMENT_CLASSES=javax.servlet.Servlet
        // 或者org.springframework.web.context.ConfigurableWebApplicationContext
		for (String className : WEB_ENVIRONMENT_CLASSES) {
   
			if (!ClassUtils.isPresent(className, null)) {
   
				return WebApplicationType.NONE;
			}
		}
		return WebApplicationType.SERVLET;
	}

ClassUtils.isPresent方法中尝试加载传入的类,如果加载成功,则返回true,如果失败则返回false,SpringBoot使用这种方式在判断当前是什么类型的应用。

从假设我们应用中什么依赖都没有加入,那么WEB_ENVIRONMENT_CLASSESREACTIVE_WEB_ENVIRONMENT_CLASS或者MVC_WEB_ENVIRONMENT_CLASS都是加载失败的,最终返回WebApplicationType.NONE

从另一个方面来说,如果我们想构建一个SpringMVC的web应用,那么只需要加入如下依赖:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

此时,SpringBoot会帮我们间接依赖SpringMVC所需要的包,那么就间接引入了org.springframework.web.context.Conf

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值