Spring Boot(未完)

这年头新项目不用 Spring Boot 的大概想法比较异于常人😅

代码基于 Spring Boot 2.0

SpringApplication启动

一般一个module Spring Boot 都会生成一个启动类,类似于下面

@SpringBootApplication
@MapperScan("com.yuantu.billmanager.mapper")
public class WebApplication {

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

我们首先进入 SpringApplication.run 这里调用了另一个 SpringApplication.run

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

继续下一个方法,这个 run 方法里面是可以放入多个 primarySource 的,具体使用情况我们以后再看

这里调用了 SpringApplication 的构造函数,然后又运行 run 方法(妈耶你怎么还没执行😰)

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

我们先来看构造函数,再往下,我们看看之前 Spring 让人崩溃且记不住的配置到底怎么处理了。

public SpringApplication(Class<?>... primarySources) {
    this(null, primarySources);
}

@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    this.resourceLoader = resourceLoader;
    //校验
    Assert.notNull(primarySources, "PrimarySources must not be null");
    //保存primarySources
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    //判断是否是web应用
    this.webApplicationType = deduceWebApplicationType();
    setInitializers((Collection) getSpringFactoriesInstances(
				ApplicationContextInitializer.class));
    //寻找Listener
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    //找到含有main函数的类
    this.mainApplicationClass = deduceMainApplicationClass();
}

构造完毕以后,我们终于要执行 run 方法了

public ConfigurableApplicationContext run(String... args) {
    //Spring提供的计时器
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    //配置Headless,告诉程序我没有显示器等硬件
    configureHeadlessProperty();
    //获取Listeners
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(
            args);
        //准备环境
        ConfigurableEnvironment environment = prepareEnvironment(listeners,
            applicationArguments);
        //配置ignore,默认为true,不扫描BeanInfo类
        configureIgnoreBeanInfo(environment);
        //绘制Banner,这里可以自己生成一个Banner.txt文件来代替
        Banner printedBanner = printBanner(environment);
        //生成上下文容器
        context = createApplicationContext();
        exceptionReporters = getSpringFactoriesInstances(
            SpringBootExceptionReporter.class,
            new Class[] { ConfigurableApplicationContext.class }, context);
        prepareContext(context, environment, listeners, applicationArguments,
	            printedBanner);
        //刷新容器
        refreshContext(context);
        //里面是空的……空的……大概可以用来实现一些特殊需求
        afterRefresh(context, applicationArguments);
        //停止计时器
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass)
                .logStarted(getApplicationLog(), stopWatch);
        }
        listeners.started(context);
        //这里查找实现了ApplicationRunner和CommandLineRunner的类,可以再这两个类里面加希望Spring初始化以后执行的内容,SpringMVC的话一般使用Listener来实现。
        callRunners(context, applicationArguments);
        }catch (Throwable ex) {
            handleRunFailure(context, listeners, exceptionReporters, ex);
            throw new IllegalStateException(ex);
        }
        listeners.running(context);
        return context;
    }