springBoot深度解析-01springApplication特性介绍

本文将深入介绍springBoot框架得特性,此处可助您了解springBoot自身特性,为后续工程架构铺平道路

1、springBoot应用

springApplication类提供了一个方便得方式来引导启动spring应用得main方法。在许多情况下您可以委托给静态SpringApplication.run方法,如下例所示:

@SpringBootApplication
public class MyApplication {

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

}

应用程序启动后 ,您将会从控制台上看到如下:

 .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::   v2.5.6

2021-02-03 10:33:25.224  INFO 17321 --- [           main] o.s.b.d.s.s.SpringAppplicationExample    : Starting SpringAppplicationExample using Java 1.8.0_232 on mycomputer with PID 17321 (/apps/myjar.jar started by pwebb)
2021-02-03 10:33:25.226  INFO 17900 --- [           main] o.s.b.d.s.s.SpringAppplicationExample    : No active profile set, falling back to default profiles: default
2021-02-03 10:33:26.046  INFO 17321 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2021-02-03 10:33:26.054  INFO 17900 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-02-03 10:33:26.055  INFO 17900 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.41]
2021-02-03 10:33:26.097  INFO 17900 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-02-03 10:33:26.097  INFO 17900 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 821 ms
2021-02-03 10:33:26.144  INFO 17900 --- [           main] s.tomcat.SampleTomcatApplication         : ServletContext initialized
2021-02-03 10:33:26.376  INFO 17900 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2021-02-03 10:33:26.384  INFO 17900 --- [           main] o.s.b.d.s.s.SpringAppplicationExample    : Started SampleTomcatApplication in 1.514 seconds (JVM running for 1.823)

默认情况下,日志消息显示info级别,包括一些相关的启动详细信息,例如启动应用程序的用户。如果您需要除 之外的日志级别INFO,您可以设置它,如日志级别中所述。应用程序版本是使用主应用程序类包中的实现版本确定的。可以通过设置spring.main.log-startup-info为关闭启动信息记录false。这也将关闭应用程序的活动配置文件的日志记录。

1.1启动失败

如果您的应用程序无法启动,注册FailureAnalyzers有机会提供专门的错误消息和解决问题的具体操作。例如,如果您在端口上启动 Web 应用程序8080并且该端口已在使用中,您应该会看到类似于以下消息的内容:

***************************
APPLICATION FAILED TO START
***************************

Description:

Embedded servlet container failed to start. Port 8080 was already in use.

Action:

Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.

如果没有全局异常处理,您任然可以显示完整得条件报告以更好地了解除了什么问题。要做到这一点,你需要开启debug级别日志或者以debug级别启动程序

例如,如果您使用java -jar 运行您得程序,以debug级别启动,您可以如下方式操作

$ java -jar myproject-0.0.1-SNAPSHOT.jar --debug

1.2.延迟初始化

        SpringApplication允许延迟初始化应用程序。启用延迟初始化后,bean 将在需要时创建,而不是在应用程序启动期间创建。因此,启用延迟初始化可以减少应用程序启动所需的时间。在 Web 应用程序中,启用延迟初始化将导致许多与 Web 相关的 bean 在收到 HTTP 请求之前不会被初始化。

        延迟初始化的一个缺点是它会延迟发现应用程序的问题。如果一个错误配置的 bean 被延迟初始化,那么在启动过程中将不再发生故障,并且只有在 bean 初始化时问题才会变得明显。还必须注意确保 JVM 有足够的内存来容纳所有应用程序的 bean,而不仅仅是那些在启动期间初始化的 bean。由于这些原因,默认情况下不启用延迟初始化,建议在启用延迟初始化之前对 JVM 的堆大小进行微调。

        可以使用lazyInitializationon 方法SpringApplicationBuildersetLazyInitializationon方法以编程方式启用延迟初始化SpringApplication。或者,可以使用spring.main.lazy-initialization以下示例中所示的属性启用它(即在配置文件中配置以下属性):

spring.main.lazy-initialization=true

1.3.自定义控制台打印横幅

        可以通过将banner.txt文件添加到类路径或将spring.banner.location属性设置为此类文件的位置来更改启动时打印的横幅。如果文件的编码不是 UTF-8,您可以设置spring.banner.charset. 除了一个文本文件,你还可以添加一个banner.gifbanner.jpgbanner.png图像文件到类路径或设置spring.banner.image.location属性。图像被转换为​​ ASCII 艺术表现形式并打印在任何文本横幅上方。

横幅得变量如下

变量描述

${application.version}

应用程序的版本号,如MANIFEST.MF. 例如,Implementation-Version: 1.0打印为1.0.

${application.formatted-version}

应用程序的版本号,如在 中声明MANIFEST.MF并为显示设置格式(用方括号括起来并以 为前缀v)。例如(v1.0)

${spring-boot.version}

您正在使用的 Spring Boot 版本。例如2.6.0

${spring-boot.formatted-version}

您正在使用的 Spring Boot 版本,已格式化以显示(用括号括起来并以 为前缀v)。例如(v2.6.0)

${Ansi.NAME}(或${AnsiColor.NAME}${AnsiBackground.NAME}${AnsiStyle.NAME})

NAMEANSI 转义码的名称在哪里。详情请参阅AnsiPropertySource

${application.title}

您的应用程序的标题,如MANIFEST.MF. 例如Implementation-Title: MyApp打印为MyApp.

如下图示例:

 您还可以使用该spring.main.banner-mode属性来确定横幅是否必须打印在System.outconsole)、发送到配置的记录器 ( log) 或根本不生成 ( off)。

打印的横幅在以下名称下注册为单例 bean:springBootBanner.

1.4.自定义SpringApplication

如果SpringApplication默认设置不合您的口味,您可以改为创建本地实例并对其进行自定义。例如,要关闭横幅,您可以编写:

package com.example.demo;

import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(DemoApplication.class);
        application.setBannerMode(Banner.Mode.OFF);
        application.run(args);
    }

}

1.5.流利得构建器API

如果您需要构建ApplicationContext层次结构(具有父/子关系的多个上下文),或者如果您更喜欢使用“流畅”构建器 API,则可以使用SpringApplicationBuilder.

SpringApplicationBuilder让要链接的多个方法调用,并且包括parentchild其让你创建层次结构,以显示在下面的示例性方法:

new SpringApplicationBuilder()
        .sources(Parent.class)
        .child(Application.class)
        .bannerMode(Banner.Mode.OFF)
        .run(args);

 1.6.应用程序可用性

        在平台上部署时,应用程序可以使用Kubernetes Probes等基础设施向平台提供有关其可用性的信息。Spring Boot 包括对常用“活跃”和“就绪”可用性状态的开箱即用支持。如果您使用 Spring Boot 的“执行器”支持,那么这些状态将作为健康端点组公开。

此外,您还可以通过将ApplicationAvailability接口注入您自己的 bean来获取可用性状态。

1.6.1活跃状态

        应用程序的“活跃度”状态表明它的内部状态是否允许它正常工作,或者如果它当前失败则自行恢复。损坏的“Liveness”状态意味着应用程序处于无法恢复的状态,基础设施应该重新启动应用程序

一般来说,“Liveness”状态不应基于外部检查,例如Health 检查。如果确实如此,则出现故障的外部系统(数据库、Web API、外部缓存)将触发整个平台的大规模重启和级联故障。

Spring Boot 应用程序的内部状态主要由 Spring 表示ApplicationContext。如果应用程序上下文已成功启动,Spring Boot 会假定应用程序处于有效状态。一旦上下文刷新,应用程序就被认为是活动的,请参阅Spring Boot 应用程序生命周期和相关的应用程序事件

1.6.2.准备状态

应用程序得就绪状态表明应用程序是否已准备好处理流量。失败的“就绪”状态告诉平台它现在不应将流量路由到应用程序。这通常在启动过程中发生的,而CommandLineRunnerApplicationRunner组件正在处理,或在任何时候,如果应用程序决定实在是太忙了额外的流量。

1.6.3. 管理应用程序可用性状态

        应用程序组件可以通过注入ApplicationAvailability接口并在其上调用方法,随时检索当前的可用性状态。更多的时候,应用程序会想要监听状态更新或更新应用程序的状态。

例如,我们可以将应用程序的“Readiness”状态导出到一个文件中,这样 Kubernetes 的“exec Probe”就可以查看这个文件:

@Component
public class MyReadinessStateExporter {

    @EventListener
    public void onStateChange(AvailabilityChangeEvent<ReadinessState> event) {
        switch (event.getState()) {
        case ACCEPTING_TRAFFIC:
            // create file /tmp/healthy
            break;
        case REFUSING_TRAFFIC:
            // remove file /tmp/healthy
            break;
        }
    }
}

我们还可以在应用程序中断且无法恢复时更新应用程序的状态:1.

@Component
public class MyLocalCacheVerifier {

    private final ApplicationEventPublisher eventPublisher;

    public MyLocalCacheVerifier(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }

    public void checkLocalCache() {
        try {
            // ...
        }
        catch (CacheCompletelyBrokenException ex) {
            AvailabilityChangeEvent.publish(this.eventPublisher, ex, LivenessState.BROKEN);
        }
    }

}

 1.7.应用程序事件和侦听器

        除了通常的 Spring Framework 事件(例如 )之外ContextRefreshedEvent,a SpringApplication还会发送一些额外的应用程序事件。

        某些事件实际上ApplicationContext是在创建之前触发的,因此您不能将这些事件注册为@Bean. 您可以使用SpringApplication.addListeners(…​)方法或SpringApplicationBuilder.listeners(…​)方法注册它们。

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

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

当您的应用程序运行时,应用程序事件按以下顺序发送:

  1. AnApplicationStartingEvent在运行开始时发送,但在任何处理之前发送,除了侦听器和初始化程序的注册。

  2. 一个ApplicationEnvironmentPreparedEvent当被发送Environment到中已知的上下文中使用,但是在创建上下文之前。

  3. 一个ApplicationContextInitializedEvent在当发送ApplicationContext准备和ApplicationContextInitializers一直呼吁,但被加载任何bean定义之前。

  4. ApplicationPreparedEvent在刷新开始之前但在加载 bean 定义之后发送一个。

  5. AnApplicationStartedEvent在上下文刷新后但在调用任何应用程序和命令行运行程序之前发送。

  6. 紧随AvailabilityChangeEvent其后发送 ,LivenessState.CORRECT以指示应用程序被视为实时应用程序。

  7. 在调用ApplicationReadyEvent任何应用程序和命令行运行程序后发送一个。

  8. AvailabilityChangeEvent在 with 之后立即发送一个,ReadinessState.ACCEPTING_TRAFFIC以指示应用程序已准备好为请求提供服务。

  9. 一个ApplicationFailedEvent如果在启动时异常发送。

上面的列表只包括SpringApplicationEvent绑定到 a 的 s SpringApplication。除此之外,以下事件也在 之后ApplicationPreparedEvent和之前发布ApplicationStartedEvent

  • 准备好 WebServerInitializedEvent后发送A。和分别是 servlet 和反应式变体。WebServerServletWebServerInitializedEventReactiveWebServerInitializedEvent

  • 刷新ContextRefreshedEvent时发送A。ApplicationContext

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

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

1.8.网络环境

SpringApplication尝试ApplicationContext代表您创建正确的类型。用于确定 a 的算法WebApplicationType如下:

  • 如果存在 Spring MVC,AnnotationConfigServletWebServerApplicationContext则使用an

  • 如果 Spring MVC 不存在而 Spring WebFlux 存在,AnnotationConfigReactiveWebServerApplicationContext则使用

  • 否则,AnnotationConfigApplicationContext使用

这意味着如果您WebClient在同一个应用程序中使用 Spring MVC 和来自 Spring WebFlux的 new ,则默认情况下将使用 Spring MVC。您可以通过调用轻松覆盖它setWebApplicationType(WebApplicationType)

还可以ApplicationContext通过调用完全控制使用的类型setApplicationContextClass(…​)

1.9.访问应用程序参数

如果您需要访问传递给 的应用程序参数SpringApplication.run(…​),您可以注入一个org.springframework.boot.ApplicationArgumentsbean。所述ApplicationArguments接口提供访问两个原始String[]以及解析参数optionnon-option参数,如下面的例子所示:

@Component
public class MyBean {

    public MyBean(ApplicationArguments args) {
        boolean debug = args.containsOption("debug");
        List<String> files = args.getNonOptionArgs();
        if (debug) {
            System.out.println(files);
        }
        // if run with "--debug logfile.txt" prints ["logfile.txt"]
    }
}

 1.10. 使用 ApplicationRunner 或 CommandLineRunner

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

该合约非常适合应在应用程序启动之后但在开始接受流量之前运行的任务。

所述CommandLineRunner接口提供访问的应用程序的参数作为一个字符串数组,而ApplicationRunner用途ApplicationArguments接口前面讨论。以下示例显示了CommandLineRunner一个run方法:

@Component
public class MyCommandLineRunner implements CommandLineRunner {

    @Override
    public void run(String... args) {
        // Do something...
    }
}

        如果几个CommandLineRunnerApplicationRunner豆类中定义必须在一个特定的顺序被调用,您还可以实现org.springframework.core.Ordered接口或使用org.springframework.core.annotation.Order注解。

1.11. 申请退出

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

此外,org.springframework.boot.ExitCodeGenerator如果bean希望在SpringApplication.exit()调用时返回特定的退出代码,它们可以实现该接口。然后可以将此退出代码传递给以将System.exit()其作为状态代码返回,如以下示例所示:

@SpringBootApplication
public class MyApplication {

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

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

}

此外,ExitCodeGenerator接口可以通过异常来实现。当遇到这样的异常时,Spring Boot 会返回实现getExitCode()方法提供的退出码。

1.12. 管理功能

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

1.13. 应用程序启动跟踪

在应用程序启动期间,SpringApplicationApplicationContext执行许多与应用程序生命周期、bean 生命周期甚至处理应用程序事件相关的任务。有了ApplicationStartup,Spring Framework允许您使用StartupStep对象跟踪应用程序启动顺序。收集这些数据是为了分析目的,或者只是为了更好地了解应用程序启动过程。

您可以ApplicationStartup在设置SpringApplication实例时选择一个实现。例如,要使用BufferingApplicationStartup,您可以编写:

@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(MyApplication.class);
        application.setApplicationStartup(new BufferingApplicationStartup(2048));
        application.run(args);
    }

}

第一个可用的实现FlightRecorderApplicationStartup是由 Spring Framework 提供的。它将特定于 Spring 的启动事件添加到 Java Flight Recorder 会话中,用于分析应用程序并将其 Spring 上下文生命周期与 JVM 事件(例如分配、GC、类加载......)相关联。配置完成后,您可以通过在启用飞行记录器的情况下运行应用程序来记录数据:

$ java -XX:StartFlightRecording:filename=recording.jfr,duration=10s -jar demo.jar

Spring Boot 随附BufferingApplicationStartup变体;此实现旨在缓冲启动步骤并将它们排入外部指标系统。应用程序可以BufferingApplicationStartup在任何组件中请求类型的 bean 。

Spring Boot 还可以配置为公开一个startup端点,该端点以 JSON 文档的形式提供此信息。


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

疯狂攻城师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值