20191110 Spring Boot官方文档学习(4.1)

4. Spring Boot功能

4.1。Spring应用

便捷的启动方式:

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

SpingBoot默认日志级别是INFO

4.1.1。启动失败

启动失败时,FailureAnalyzers会报告错误信息。

4.1.2。延迟初始化(懒加载)

SpringApplication允许延迟初始化应用程序。启用延迟初始化后,将根据需要创建bean,而不是在应用程序启动期间创建bean。

以下方式可以启动延迟初始化:

  1. SpringApplicationBuilder启动
org.springframework.boot.builder.SpringApplicationBuilder#lazyInitialization
  1. SpringApplication指定
org.springframework.boot.SpringApplication#setLazyInitialization
  1. 属性配置
spring.main.lazy-initialization=true

对bean使用延迟初始化,可以使用@Lazy注解。

4.1.3。定制Banner

banner.txt 或图像文件(banner.gifbanner.jpgbanner.png)放在类路径,或通过设置属性指定路径spring.banner.location(图像为spring.banner.image.location)。图像将转换为ASCII

banner.txt文件内部,可以使用以下任意占位符,参考:
变量 | 描述
---|---
${application.version} | 您的应用程序的版本号,如MANIFEST.MF中所述。例如,Implementation-Version: 1.0打印为1.0。
${application.formatted-version} | 您的应用程序的版本号,如MANIFEST.MF中所述,并进行了格式显示(用括号括起来,并带有前缀v)。例如(v1.0)。
${spring-boot.version} | 您正在使用的Spring Boot版本。例如2.2.0.RELEASE。
${spring-boot.formatted-version} | 您正在使用的Spring Boot版本,其格式用于显示(用括号括起来,并带有前缀v)。例如(v2.2.0.RELEASE)。
${Ansi.NAME}(或${AnsiColor.NAME}${AnsiBackground.NAME}${AnsiStyle.NAME}) | NAME是指ANSI转义代码的名称。有关详细信息,请参见AnsiPropertySource
${application.title} | 您的应用程序的标题,如MANIFEST.MF中所述。例如Implementation-Title: MyApp打印为MyApp。

使用 org.springframework.boot.SpringApplication#setBanner 以编程方式生成Banner

属性spring.main.banner-mode 指定打印Banner的方式。

打印Banner的单实例bean的id是:springBootBanner

4.1.4。自定义SpringApplication

传递给SpringApplication构造函数的参数是Spring bean的配置源。在大多数情况下,这些是对@Configuration类的引用,但它们也可以是对XML配置或应扫描的程序包的引用。

也可以通过使用application.properties文件来配置。有关详细信息参见SpringApplication

有关配置选项的完整列表,参见org.springframework.boot.SpringApplication

4.1.5。流式Builder API

org.springframework.boot.builder.SpringApplicationBuilder

示例:

new SpringApplicationBuilder(SpringbootApplication.class).profiles("server")
        .properties("transport=local").run(args);

创建ApplicationContext层次结构时有一些限制。例如,Web组件必须包含在子上下文中,并且父和子上下文都使用相同的Environment

4.1.6。应用程序事件和监听器

有些事件实际上是在创建ApplicationContext之前触发的,因此您无法将监听器注册为@Bean来监听事件。您可以使用SpringApplication.addListeners(...)方法或SpringApplicationBuilder.listeners(...)方法注册它们。

如果您希望这些侦听器自动注册,而不管创建应用程序的方式如何,可以将META-INF/spring.factories文件添加到项目中,并使用org.springframework.context.ApplicationListener键引用您的侦听器,如以下示例所示:

org.springframework.context.ApplicationListener = com.example.project.MyListener

分析启动方法
org.springframework.boot.SpringApplication#run(java.lang.String...)
应用程序事件在您的应用程序运行时按以下顺序发送,这些事件是绑定在SpringApplication上SpringApplicationEvents

  1. ApplicationStartingEvent在运行开始时发送 ,但在进行任何处理之前(侦听器和初始化程序的注册除外)发送。
listeners.starting();
  1. ApplicationEnvironmentPreparedEvent当Environment被发送到中已知的上下文中使用,但是在创建上下文之前。
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
  1. ApplicationContextInitializedEventApplicationContext准备好且已调用ApplicationContextInitializers之后,但未加载任何bean定义之前,发送。
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
listeners.contextPrepared(context);
  1. ApplicationPreparedEvent在刷新开始之前但在加载bean定义之后发送。
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
listeners.contextLoaded(context);
  1. ApplicationStartedEvent上下文已被刷新后,但是application runnerscommand-line runners被调用前,发送。
listeners.started(context);
  1. ApplicationReadyEventapplication runnerscommand-line runners被调用后发送。它指示该应用程序已准备就绪,可以处理请求。
listeners.running(context);
  1. ApplicationFailedEvent在启动异常时发送。
handleRunFailure(context, ex, exceptionReporters, listeners);

额外的事件,在ApplicationPreparedEventApplicationStartedEvent之间发送:

  1. ContextRefreshedEventApplicationContext刷新后发送。
  2. WebServerInitializedEvent在WebServer准备就绪后发送。ServletWebServerInitializedEventReactiveWebServerInitializedEvent分别是servlet和响应式servlet的变种。

应用程序事件是通过使用Spring Framework的事件发布机制发送的。此机制的一部分确保在子级上下文中发布给侦听器的事件也会在任何祖先上下文中发布给侦听器。因此,如果您的应用程序使用SpringApplication实例的层次结构,则侦听器可能会收到同一类型的应用程序事件的多个实例。

为了使您的侦听器能够区分其上下文的事件和后代上下文的事件,它应请求注入其应用程序上下文,然后将注入的上下文与事件的上下文进行比较。可以通过实现ApplicationContextAware来注入上下文,或者,如果侦听器是bean,则可以使用@Autowired注入上下文。

4.1.7。Web Environment

SpringApplication试图创建正确类型的ApplicationContext。确定WebApplicationType的算法非常简单:

  • 如果存在Spring MVC,则使用AnnotationConfigServletWebServerApplicationContext
  • 如果不存在Spring MVC且存在Spring WebFlux,则使用AnnotationConfigReactiveWebServerApplicationContext
  • 否则,使用AnnotationConfigApplicationContext

参考源码:

org.springframework.boot.SpringApplication#run(java.lang.String...)
    context = createApplicationContext();


org.springframework.boot.SpringApplication#SpringApplication(org.springframework.core.io.ResourceLoader, java.lang.Class<?>...)
    this.webApplicationType = WebApplicationType.deduceFromClasspath();

在同一应用程序中使用Spring MVCSpring WebFlux中的新功能,则默认情况下将使用Spring MVC。可以通过调用org.springframework.boot.SpringApplication#setWebApplicationType轻松覆盖它。也可以通过调用org.springframework.boot.SpringApplication#setApplicationContextClass 直接设置ApplicationContext

4.1.8。访问应用程序参数

如果您需要访问传递给SpringApplication.run(...)的应用程序参数,则可以注入org.springframework.boot.ApplicationArgumentsBeanApplicationArguments接口提供对原始String[]参数以及已解析option和non-option参数的访问,如以下示例所示:

@Component
public class MyBean {
    @Autowired
    public MyBean(ApplicationArguments args) {
        boolean debug = args.containsOption("debug");
        List<String> nonOptionArgs = args.getNonOptionArgs();
        // if run with "--debug logfile.txt" debug=true, files=["logfile.txt"]
    }
}

Spring Boot也向Spring Environment注册了一个CommandLinePropertySource。这样,您还可以使用@Value注释注入单个应用程序参数。

4.1.9。使用ApplicationRunnerCommandLineRunner

如果启动SpringApplication后需要运行一些特定的代码,则可以实现ApplicationRunnerCommandLineRunner接口。这两个接口以相同的方式工作,并提供一个单一的run方法,该方法在SpringApplication.run(...)完成之前就被调用。

参考源码:

org.springframework.boot.SpringApplication#run(java.lang.String...)
    callRunners(context, applicationArguments);

Runner执行时不是异步调用,而是在ApplicationStartedEvent事件和ApplicationReadyEvent之间执行。

ApplicationRunnerCommandLineRunner接口的不同之处在于入参不同,前者是ApplicationArguments,后者是String...

如果有多个Runner,需要指定执行顺序时,可以实现org.springframework.core.Ordered接口或使用org.springframework.core.annotation.Order注解。

4.1.10。Application Exit

每个SpringApplication都向JVM注册一个关闭钩子,以确保ApplicationContext退出时正常关闭。可以使用所有标准的Spring生命周期回调(例如DisposableBean接口或@PreDestroy注解)。

如果希望在SpringApplication.exit()被调用时返回特定的退出代码,则可以实现org.springframework.boot.ExitCodeGenerator接口。然后可以将此退出代码传递给System.exit(),以将其作为状态代码返回。

而且,Exception实现ExitCodeGenerator接口后,当抛出异常时,Spring Boot返回由实现的getExitCode()方法提供的退出代码。

示例:

@SpringBootApplication
public class SpringbootApplication {

    @Bean
    public ExitCodeGenerator exitCodeGenerator() {
        return () -> 42;
    }

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

}

直接停止虚拟机不能返回特定的退出代码。

4.1.11。管理员功能

通过指定spring.application.admin.enabled属性,可以为应用程序启用与管理员相关的功能。这将在MBeanServer平台上公开SpringApplicationAdminMXBean。您可以使用此功能来远程管理Spring Boot应用程序。此功能对于任何服务包装器实现也可能很有用。

如果您想知道应用程序在哪个HTTP端口上运行,请通过键local.server.port获取属性。

上一篇:spring boot学习(3): SpringApplication 事件监听


下一篇:springboot启动事件监听器退出钩子