Springboot 2.4.4启动类源码分析

目录

1.springboot启动类

 2.run方法

3.SpringApplication构造方法

3.1 this.sources = new LinkedHashSet();

3.2 this.bannerMode = Mode.CONSOLE;

3.3 this.logStartupInfo = true;

3.4 this.addCommandLineProperties = true;

3.5 this.addConversionService = true;

3.6 this.headless = true;

3.7 this.registerShutdownHook = true;

3.8 this.additionalProfiles = Collections.emptySet();

3.9 this.isCustomEnvironment = false;


1.springboot启动类

   springboot最简单且最基础的启动类。接下来我们进入run方法。

@SpringBootApplication
public class DemoBckApplication {

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

}

 2.run方法

可以看到返回的是(new SpringApplication(primarySources)).run(args);  这里先将启动类传入的class参数转成数组对象,再传入SpringApplication类的构造方法。那我们先看一下SpringApplication类的构造方法,看看里面初始化了哪些属性。

   //primarySource参数:DemoBckApplication.class 
   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);
    }

3.SpringApplication构造方法

附一张debugger的图,SpringApplication初始化的属性都在里面了。然后我们来看看部分属性的含义和用途,大概了解即可,具体的我们待会看代码分析。

Springboot 2.4.4启动类源码分析_第1张图片

3.1 this.sources = new LinkedHashSet();

aa

3.2 this.bannerMode = Mode.CONSOLE;

该属性是用来打印springboot启动时的图标。
.   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/  ___)| |_)| | | | | || (_| |  ) ) ) )
'  |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot ::        (v1.3.3.RELEASE)
Mode是org.springframework.boot.Banner类中静态enum类型。
OFF:关闭
CONSOLE:打印在控制台
LOG:打印到日志

3.3 this.logStartupInfo = true;

true的话则打印jvm的启动和运行信息。包括启动类、java版本、pid等

3.4 this.addCommandLineProperties = true;

通过命令行参数向application.properties中添加属性配置,例如执行java -jar test.jar –server.port=9000,将向application.properties中新增一个属性配置。

3.5 this.addConversionService = true;

加载默认的类型转换和格式化类 (ApplicationConversionService)

   public static void addApplicationConverters(ConverterRegistry registry) {
        addDelimitedStringConverters(registry);
        registry.addConverter(new StringToDurationConverter());
        registry.addConverter(new DurationToStringConverter());
        registry.addConverter(new NumberToDurationConverter());
        registry.addConverter(new DurationToNumberConverter());
        registry.addConverter(new StringToPeriodConverter());
        registry.addConverter(new PeriodToStringConverter());
        registry.addConverter(new NumberToPeriodConverter());
        registry.addConverter(new StringToDataSizeConverter());
        registry.addConverter(new NumberToDataSizeConverter());
        registry.addConverter(new StringToFileConverter());
        registry.addConverter(new InputStreamSourceToByteArrayConverter());
        registry.addConverterFactory(new LenientStringToEnumConverterFactory());
        registry.addConverterFactory(new LenientBooleanToEnumConverterFactory());
        if (registry instanceof ConversionService) {
            addApplicationConverters(registry, (ConversionService)registry);
        }

    }

    public static void addApplicationFormatters(FormatterRegistry registry) {
        registry.addFormatter(new CharArrayFormatter());
        registry.addFormatter(new InetAddressFormatter());
        registry.addFormatter(new IsoOffsetFormatter());
    }

3.6 this.headless = true;

开启java的headless模式。此模式允许java在没有显示器、鼠标等设备缺失的情况下启动服务,对于部署在服务器的程序来说是很有必要的。

System.setProperty("java.awt.headless", System.getProperty("java.awt.headless", Boolean.toString(this.headless)));

3.7 this.registerShutdownHook = true;

创建线程,该线程用来在java程序关闭后释放资源(即Spring Shutdown Hook)

   //启动类方法
   private void refreshContext(ConfigurableApplicationContext context) {
        if (this.registerShutdownHook) {
            try {
                context.registerShutdownHook();
            } catch (AccessControlException var3) {
            }
        }

        this.refresh((ApplicationContext)context);
    }

    //创建线程
    public void registerShutdownHook() {
        if (this.shutdownHook == null) {
            this.shutdownHook = new Thread("SpringContextShutdownHook") {
                public void run() {
                    synchronized(AbstractApplicationContext.this.startupShutdownMonitor) {
                        AbstractApplicationContext.this.doClose();
                    }
                }
            };
            //线程注册
            Runtime.getRuntime().addShutdownHook(this.shutdownHook);
        }

    }

   //关闭
   protected void doClose() {
        if (this.active.get() && this.closed.compareAndSet(false, true)) {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Closing " + this);
            }

            if (!NativeDetector.inNativeImage()) {
                LiveBeansView.unregisterApplicationContext(this);
            }

            try {
                // 发布Spring 应用上下文的关闭事件,让监听器们有机会在应用关闭之前做出一些响应
                this.publishEvent((ApplicationEvent)(new ContextClosedEvent(this)));
            } catch (Throwable var3) {
                this.logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", var3);
            }

            if (this.lifecycleProcessor != null) {
                try {
                    // 执行lifecycleProcessor的关闭方法,让Lifecycle们有机会在应用关闭之前做出一些响应
                    this.lifecycleProcessor.onClose();
                } catch (Throwable var2) {
                    this.logger.warn("Exception thrown from LifecycleProcessor on context close", var2);
                }
            }
            // 销毁IOC容器里所有单例Bean
            this.destroyBeans();
            // 关闭BeanFactory
            this.closeBeanFactory();
            // 勾子函数,让子类实现后做各自的资源清理,比如ServletWebServerApplicationContext会实现该勾子函数关闭内嵌的WebServer(Tomcat)
            this.onClose();
            if (this.earlyApplicationListeners != null) {
                this.applicationListeners.clear();
                this.applicationListeners.addAll(this.earlyApplicationListeners);
            }

            this.active.set(false);
        }

    }

3.8 this.additionalProfiles = Collections.emptySet();

 默认为空,即使用springboot默认配置文件。可以调用 SpringApplication的setAdditionalProfiles()实现spring boot的profile指定,根据指定参数不同读取“dev”、“test”等不同环境的配置。如果是在配置文件中配置spring.profiles.active: dev,读取配置的方法在后面的run方法中,文章后面进行介绍。


private void configureAdditionalProfiles(ConfigurableEnvironment environment) {
        //如果additionalProfiles不为空,则获取配置并设置
        if (!CollectionUtils.isEmpty(this.additionalProfiles)) {
            //获取spring.profiles.active 配置
            Set profiles = new LinkedHashSet(Arrays.asList(environment.getActiveProfiles()));
            if (!profiles.containsAll(this.additionalProfiles)) {
                profiles.addAll(this.additionalProfiles);
                environment.setActiveProfiles(StringUtils.toStringArray(profiles));
            }
        }

    }

3.9 this.isCustomEnvironment = false;

加载环境配置

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
        //创建默认环境配置
        ConfigurableEnvironment environment = this.getOrCreateEnvironment();
        //加载默认的类型转换和格式化类
        this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
        //默认配置放入ConfigurationPropertySources
        ConfigurationPropertySources.attach((Environment)environment);
        listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
        DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
        this.configureAdditionalProfiles((ConfigurableEnvironment)environment);
        this.bindToSpringApplication((ConfigurableEnvironment)environment);
        if (!this.isCustomEnvironment) {
            //读取application配置文件并加载
            environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
        }
        //将application配置放入,并提高至最高优先级
        ConfigurationPropertySources.attach((Environment)environment);
        return (ConfigurableEnvironment)environment;
    }

3.10 this.lazyInitialization = false;

你可能感兴趣的:(java,spring,boot)