spring-boot-2.3.7启动过程(二):run()方法

spring-boot-2.3.7启动过程(二):run()方法

1、run方法的执行过程。

public ConfigurableApplicationContext run(String... args) {
        //创建时间对象并启动计时。
        StopWatch stopWatch = new StopWatch();
        //设置任务名称。
        stopWatch.start();
        //这就是传说中的 IOC容器,实则是个 ConfigurableApplicationContext 对象,先创建出来,再往里面填东西。
        ConfigurableApplicationContext context = null;
        Collection exceptionReporters = new ArrayList();
        //设置当前应用为 headless 模式。
        this.configureHeadlessProperty();
        //获取运行时监听器,并开始监听。
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting();

        Collection exceptionReporters;
        try {
            //准备环境。
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            //打印 banner。
            Banner printedBanner = this.printBanner(environment);
            //创建context。
            context = this.createApplicationContext();
            exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
            //准备context。
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            //刷新context。
            this.refreshContext(context);
            this.afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }

            listeners.started(context);
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            this.handleRunFailure(context, var10, exceptionReporters, listeners);
            throw new IllegalStateException(var10);
        }

        try {
            listeners.running(context);
            return context;
        } catch (Throwable var9) {
            this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var9);
        }
    }

1、 创建时间对象并启动计时。

2、创建 IOC 容器。

3、设置当前应用为 headless 模式。将应用程序设置为这种模式,是为了告诉程序,“你所在的服务器上缺少些硬件,没有显示器、鼠标、或者其他”。这就是一个赋值过程,不需要深究。

4、获取运行时监听器,并开始监听。

5、准备环境。应用程序运行在服务器上,而且它的运行需要依赖一些资源,比如 JDK、maven 库、文件编码格式等等。那应用程序是怎么知道这些资源都放在哪里的?或者这些属性值是什么?从而能正确读取。是因为应用程度在启动过程中创建了环境对象,它里面有个字段(成员变量):MutablePropertySources propertySources ,所有的资源属性在应用程度启动过程中被包装成 propertySource 存放在 propertySources 中。后面开发者如果有需要直接在 环境对象中拿这些资源就可以了。除此以外,开发者可以使用 @propertySource 将自定义的配置文件导入到 环境对象中,最后被代码块调用。

ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);

5.1、跟进this.prepareEnvironment(listeners, applicationArguments)。

  private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
        //创建环境对象。
        ConfigurableEnvironment environment = this.getOrCreateEnvironment();
        //配置环境对象。
        this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
        //绑定环境对象。
        ConfigurationPropertySources.attach((Environment)environment);
        //发布监听时间。
        listeners.environmentPrepared((ConfigurableEnvironment)environment);
        this.bindToSpringApplication((ConfigurableEnvironment)environment);
        if (!this.isCustomEnvironment) {
            environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
        }

        ConfigurationPropertySources.attach((Environment)environment);
        return (ConfigurableEnvironment)environment;
    }

6、打印 banner。是否打印 logo 可以在 application.properties 中配置,logo 的图案也可以修改。

7、创建 context。

8、准备 context。

9、刷新 context。将应用程序运行所需要的所有 bean(包括开发者自己写的) 加载到了 context 的 beanFactory 中。

9.1、要自动配置的类得先写好了,加上注解,包存在 .java 文件中。
9.2、在启动过程中调用 BeanFactoryPostProcesser 的某个实现类,它为需要自动配置的每一个类创造一个对应的 beanDefinition,并将所有的 beanDefinition 保存(注册) 到 context 中。(实际上是为每一个类构建键值对 className:BeanDefinion 保存到了 context 中的 beanFactory 属性的 beanDefinitionMap 属性中)。

9.3、接着再遍历 beanDefinitionMap,根据 className 从 context 中先获取对应的 bean,如果能拿到,就表示这个类已经被注册了,如果拿不到,那就通过 BeanDefinion 创建一个新 bean 注册到 context中。(实际上是从 context 中的 beanFactory 属性的 singletonObject 属性中拿 bean,如果拿不到,创建的新 bean 也是保存到 signletonObject 中)。

你可能感兴趣的:(源码解析,java,spring,开发语言)