SpringApplication理解

  SpringApplication提供了一种很方便的方式来启动spring 应用,通过使用main()方法。在很多情况下,你可以使用SpringApplication.run静态方法来委托实现;如下:

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

  

  项目启动后,如下图所示:默认情况下,显示INFO级别的日志信息,包括相关的启动详情,如springboot版本号、用户名、主机名、进程ID、项目路径、servlet容器、及项目路径等基本信息。

  1.如果你想把日志级别设为其他,可以修改application.properties中配置,如下:

logging.level.root=warn
logging.level.org.springframework.web=debug
logging.level.org.hibernate=error

  2.如果你想关闭启动日志,可以设置application.properties中的spring.main.log-startup-info为false;

spring.main.log-startup-info=false

  3.在项目启动时,你可以通过重写SpringApplication子类的logStartupInfo(boolean)来添加额外的日志信息;

1.1启动失败:

  如果应用启动失败,FailureAnalyzers会提供一个专用的错误描述和具体的解决问题的Action。例如:如果你在8080端口启了一个web应用,而这个端口已经被占用,你就可以看到下图所示的信息:

  注意:Spring Boot提供了大量的FailureAnalyzer实现,你也可以自定义实现。

  如果遇到failure analyzers不能处理的异常,你可以展示完整的conditions report以便于更好的理解错误。如使用DEBUG日志级别,或者使用java -jar,并启用debug模式:

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

1.2懒初始化(Lazy Initialization)

  懒初始化:beans在需要的时候才被创建,而不是在应用启动时;默认情况下,禁用懒加载;如果使用懒加载,必须保证JVM有足够的内存;

  优点:启用懒初始化会减少应用启动的时间。在一个web应用中,懒加载会使很多web相关的beans在接收到Http请求的时候才被初始化;

  缺点:延迟发现应用的问题。如果一个配置错误的bean被懒加载,这个错误不会在项目启动时出现,而是在该bean初始化时才被发现;

  设置懒加载的方式:

    1.编程方式:使用SpringApplicationBuilder的lazyInitialization方法或者是SpringApplication的setLazyInitialization方法;

    2.配置方式:spring.main.lazy-initialization=true

    3.当启用懒加载模式时,可以使用@Lazy(false)注解为指定beans禁用懒加载;

1.3自定义Banner

    默认Banner:Banner会在项目启动时被打印在开头;spring boot自带的Banner在SpringBootBanner类中定义,如下图所示:

/**
 * Default Banner implementation which writes the ‘Spring‘ banner.
 *
 */
class SpringBootBanner implements Banner {

    private static final String[] BANNER = { "", "  .   ____          _            __ _ _",
            " /\\\\ / ___‘_ __ _ _(_)_ __  __ _ \\ \\ \\ \\", "( ( )\\___ | ‘_ | ‘_| | ‘_ \\/ _` | \\ \\ \\ \\",
            " \\\\/  ___)| |_)| | | | | || (_| |  ) ) ) )", "  ‘  |____| .__|_| |_|_| |_\\__, | / / / /",
            " =========|_|==============|___/=/_/_/_/" };

    private static final String SPRING_BOOT = " :: Spring Boot :: ";

    private static final int STRAP_LINE_SIZE = 42;

    ......

}

  自定义banner:

    1.文本Banner:可以通过在classpath路径下添加banner.txt文件或者设置spring.banner.location属性来指定自定义Banner文件;如果文件格式不是UTF-8,可以设置spring.banner.charset属性

    2.图片Banner:在classpath路径下添加banner.gif、banner.jpg、banner.png图片或者通过spring.banner.image.location属性来指定文件;效果如下所示:

    3.编程方式:SpringApplication.setBanner(…)使用编程的方式设置banner,使用org.springframework.boot.Banner接口实现printBanner()方法;

    注意:图片转化为ASCII 艺术展示;而且显示在文本Banner上方;banner.txt文件中你可以使用如下的占位符;可以使用spring.main.banner-mode来设置是否将banner打印在控制台上(log/off);banner会被注册为单个的bean,名为springBootBanner;

${application.version}:应用版本号
${application.formatted-version}:格式化后的应用版本号,加括号及前缀“v”,例如:(v1.0)
${spring-boot.version}:spring boot的版本号,如2.2.2.RELEASE
${spring-boot.formatted-version}:格式化后的spring boot的版本号,如(v2.2.2.RELEASE)...

1.4自定义SpringApplication

  如果默认的SpringApplication不符合你的口味,你可以创建一个本地实例并自定义它。例如,你可以使用以下代码关闭banner:

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

  注意:SpringApplication构造器参数是spring beans的configuration源。大多数情况下,这些configuration源和@Configuration注解的类有关,也有可能和XML配置或者是被扫描的包有关;

  也可以使用application.properties文件来配置SpringApplication,详细内容可以查看SpringApplication JavaDoc

1.5 SpringApplicationBuilder

  如果你需要构建ApplicationContext层次结构(带有父/子的多个上下文关系),或者如果您更喜欢使用“Builder API,则可以使用SpringApplicationBuilderSpringApplicationBuilder允许使用方法链的方式来创建ApplicationContext层次结构,包括parent、child,如下所示:

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

  注意:创建ApplicationContext层级结构有一些限制条件。比如,Web组件必须存在于子上下文,而且父和子上下文使用相同的Environment。SpringApplicationBuilder JavaDoc

1.6 Application Events and Listeners

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

  注意:实际上在创建ApplicationContext之前会触发一些事件,因此我们无法将这些监听器(Listeners)注册为@Bean。你可以通过SpringApplication.addListeners(…)SpringApplicationBuilder.listeners(…)方法来注册监听器; 如果你不关心应用的创建方式,只希望这些监听器被自动注册,你可以在项目中添加一个 META-INF/spring.factories文件,并在文件中指定监听器的引用,如下所示:

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

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

  1. ApplicationStartingEvent:程序启动未执行任何处理(不包括listeners和initializers注册)
  2. ApplicationEnvironmentPreparedEvent:Environment被上下文使用但是上下文未创建前;
  3. ApplicationContextInitializedEvent:ApplicationContext准备完成 并且 调用ApplicationContextInitializers,但bean定义被加载之前
  4. ApplicationPreparedEvent:bean定义被加载后 应用上下文未刷新完成前
  5. ApplicationStartedEvent:上下文刷新完成,但 应用程序和命令行程序被吊起之前
  6. ApplicationReadyEvent:所有应用程序和命令行启动程序被吊起之后,将发送一个ApplicationReadyEvent。 它指示该应用程序已准备就绪,可以处理请求。
  7. ApplicationFailedEvent:程序启动出现异常;

  上述列表中的SpringApplicationEvents仅仅是和SpringApplication绑定的;除了这些,介于ApplicationPreparedEvent和ApplicationStartedEvent之间的event还有下列:

  1. ContextRefreshedEvent:当ApplicationContext刷新时;
  2. WebServerInitializedEvent:WebServer准备完成时;ServletWebServerInitializedEvent和ReactiveWebServerInitializedEvent分别表示servlet应用(MVC)和reactive(webflux)应用;

   注意:我们可能用不到这些应用事件,但是知道它们的存在以后处理问题可能会很方便。Spring Boot使用应用事件可以处理各式各样的任务。

  应用程序事件是通过使用Spring Framework的事件发布机制发送的。 这样的机制确保将在子上下文中发布给监听器的事件也发布到在任何祖先上下文中的监听器。 因此,如果你的应用程序是有多个SpringApplication实例的分层结构时,监听器可能会收到多个实例的相同类型的应用程序事件。

不是很理解,慢慢理解:To allow your listener to distinguish between an event for its context and an event for a descendant
context, it should request that its application context is injected and then compare the injected
context with the context of the event. The context can be injected by implementing
ApplicationContextAware or, if the listener is a bean, by using @Autowired.

1.7Web Environment

  SpringApplication总是会创建一个正确的ApplicationContext,决定WebApplicationType的算法很简单;

  • 如果当前项目是spring mvc项目,将会使用AnnotationConfigServletWebServerApplicationContext;
  • 如果当前项目是spring webflux项目,将会使用AnnotationConfigReactiveWebServerApplicationContext;
  • 其他情况下,使用AnnotationConfigApplicationContext;

1.8Accessing Application Arguments

  你可以通过注入org.springframework.boot.ApplicationArguments  bean的方式使用SpringApplication.run(…)方法中的参数,即Application Arguments;如下,项目启动时,会在控制台输出args的内容!

@SpringBootApplication
public class SampleApplication {

    public static void main(String[] args) {
        args = new String[]{"111","222"};
        SpringApplication.run(SampleApplication.class, args);
    }

    @Autowired
    public SampleApplication(ApplicationArguments args) {
        List<String> files = args.getNonOptionArgs();
        for(String str:files){
            System.out.println(str);
        }
    }
}

  注意:spring boot在spring Environment.中注册了一个CommandLinePropertySource,它允许你使用@Value注解的方式注入单个application arguments;

1.9 使用ApplicationRunner或CommandLineRunner

  一旦SpringApplication启动后,如果你想运行一些特殊的代码,你可以通过实现ApplicationRunner或CommandLineRunner接口的方式实现;两个接口工作方式相同,都只有一个run方法,在SpringApplication.run(…)完成前调用;使用方式如下:

@Component
public class MyBean implements CommandLineRunner {
  public void run(String... args) {
    // Do something...
  }
}

  注意:如果定义了多个CommandLineRunner或ApplicationRunner实现的bean,而且你必须指定调用的顺序,那么你可以额外实现org.springframework.core.Ordered接口,或者使用org.springframework.core.annotation.Order annotation注解

1.10 Application Exit

  Each SpringApplication registers a shutdown hook with the JVM to ensure that the ApplicationContext closes gracefully on exit. All the standard Spring lifecycle callbacks (such as the
DisposableBean interface or the @PreDestroy annotation) can be used.
  In addition, beans may implement the org.springframework.boot.ExitCodeGenerator interface if they wish to return a specific exit code when SpringApplication.exit() is called. This exit code can then
be passed to System.exit() to return it as a status code, as shown in the following example:
@SpringBootApplication
public class ExitCodeApplication {
@Bean
public ExitCodeGenerator exitCodeGenerator() {
return () -> 42;
}
public static void main(String[] args) {
System.exit(SpringApplication.exit(SpringApplication.run(ExitCodeApplication.class,
args)));
}
}
Also, the ExitCodeGenerator interface may be implemented by exceptions. When such an exception
is encountered, Spring Boot returns the exit code provided by the implemented getExitCode()
method.

  

原文地址:https://www.cnblogs.com/maxudong/p/12039718.html

时间: 2024-11-07 14:50:16

SpringApplication理解的相关文章

springboot SpringApplication 的十大特性

1.启动失败 如果你启动项目失败,你通过注册FailureAnalyzers 来获取错误信息和解决办法.比如你启动应用的8080端口被占用了,你将看到如下信息: *************************** APPLICATION FAILED TO START *************************** Description: Embedded servlet container failed to start. Port 8080 was already in use

SpringCloud(6)---熔断降级理解、Hystrix实战

SpringCloud(6)---熔断降级理解.Hystrix实战 一.概念 1.为什么需要熔断降级 (1)需求背景 它是系统负载过高,突发流量或者网络等各种异常情况介绍,常用的解决方案. 在一个分布式系统里,一个服务依赖多个服务,可能存在某个服务调用失败,比如超时.异常等,如何能够保证在一个依赖出问题的情况下,不会导致整体服务失败. 比如:某微服务业务逻辑复杂,在高负载情况下出现超时情况. 内部条件:程序bug导致死循环.存在慢查询.程序逻辑不对导致耗尽内存 外部条件:黑客攻击.促销.第三方系

微服务 SpringBoot 2.0(四):启动剖析之SpringApplication.run

我以为只是运行了个main方法,可却启动了服务 -- Java面试必修 引言 前一章我们讲解了启动原理的@SpringBootApplication部分,仔细跟着看代码还是很好理解,若需观看@SpringBootApplication注解部分请点击,接下来这章主要讲解run方法运行部分,run方法运行这里很枯燥乏味,所以请带好你的精气神,准备好水,因为实在是太干了. 运行启动 工具 SpringBoot版本:2.0.4 开发工具:IDEA 2018 Maven:3.3 9 JDK:1.8 我们继

Spring Cloud Hystrix理解与实践(一):搭建简单监控集群

前言 在分布式架构中,所谓的断路器模式是指当某个服务发生故障之后,通过断路器的故障监控,向调用方返回一个错误响应,这样就不会使得线程因调用故障服务被长时间占用不释放,避免故障的继续蔓延.Spring Cloud Hystrix实现了断路器,线程隔离等一系列服务保护功能,它是基于Netflix的开源框架Hystrix实现的. 目的不是介绍Hystrix的与原理.及其使用等(有时间也要记录啊),而是通过实战搭建一个简单的监控集群,使用Hystrix Dashboard仪表盘动态监控展示以此来加深对H

SpringBoot源码分析之---SpringBoot项目启动类SpringApplication浅析

源码版本说明 本文源码采用版本为SpringBoot 2.1.0BUILD,对应的SpringFramework 5.1.0.RC1 注意:本文只是从整体上梳理流程,不做具体深入分析 SpringBoot入口类 @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args

SpringBoot之SpringApplication

简介 可以用于从java主方法中引导和启动Spring应用程序的类,在默认情况下,通过以下步骤来启动应用: 创建一个ApplicationContext实例 注册CommandLinePropertySource用来暴露命令行参数作为spring的属性 refresh applicationContext,加载所有的singleton bean 触发任何CommandLineRunner bean 自定义SpringApplication 默认的启动方式,代码如下,不做深入介绍 1 Spring

通过源码理解Spring中@Scheduled的实现原理并且实现调度任务动态装载

前提 最近的新项目和数据同步相关,有定时调度的需求.之前一直有使用过Quartz.XXL-Job.Easy Scheduler等调度框架,后来越发觉得这些框架太重量级了,于是想到了Spring内置的Scheduling模块.而原生的Scheduling模块只是内存态的调度模块,不支持任务的持久化或者配置(配置任务通过@Scheduled注解进行硬编码,不能抽离到类之外),因此考虑理解Scheduling模块的底层原理,并且基于此造一个简单的轮子,使之支持调度任务配置:通过配置文件或者JDBC数据

SpringApplication对象是如何构建的? SpringBoot源码(八)

注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 本篇接 SpringBoot的启动流程是怎样的?SpringBoot源码(七) 1 温故而知新 温故而知新,我们来简单回顾一下上篇的内容,上一篇我们分析了SpringBoot的启动流程,现将关键步骤再浓缩总结下: 构建SpringApplication对象,用于启动SpringBoot: 从spring.factories配置文件中加载EventPublishingRunListener对象用于在不同的启动阶段发射不同的生命

Python——深入理解urllib、urllib2及requests(requests不建议使用?)

深入理解urllib.urllib2及requests            python Python 是一种面向对象.解释型计算机程序设计语言,由Guido van Rossum于1989年底发明,第一个公开发行版发行于1991年,Python 源代码同样遵循 GPL(GNU General Public License)协议[1] .Python语法简洁而清晰,具有丰富和强大的类库. urllib and urllib2 区别 urllib和urllib2模块都做与请求URL相关的操作,但