SpringApplication你不知道的那些事!

SpringApplication类提供了一种快捷方式来启动java程序,能够从main()方法启动Spring应用。有没有以为很简单,很方便。html

接下来将带你学习一些其余的一些关于SpringApplication东东java


SpringBoot启动


SpringApplication类提供了一种快捷方式,用于从main()方法启动Spring应用。多数状况下,你只须要将该任务委托给SpringApplication.run静态方法:git

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

当应用启动时,你应该会看到相似下面的东西:github

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

2013-07-31 00:08:16.117  INFO 56603 --- [           main] o.s.b.s.app.SampleApplication            : Starting SampleApplication v0.1.0 on mycomputer with PID 56603 (/apps/myapp.jar started by pwebb)
2013-07-31 00:08:16.166  INFO 56603 --- [           main] ationConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6e5a8246: startup date [Wed Jul 31 00:08:16 PDT 2013]; root of context hierarchy
2014-03-04 13:09:54.912  INFO 41370 --- [           main] .t.TomcatServletWebServerFactory : Server initialized with port: 8080
2014-03-04 13:09:56.501  INFO 41370 --- [           main] o.s.b.s.app.SampleApplication            : Started SampleApplication in 2.992 seconds (JVM running for 3.658)

默认状况下,会显示INFO日志消息,包括一些相关的启动细节,好比启动应用程序的用户。若是您须要一个除INFO之外的日志级别,您能够设置它,如第264节所述,“日志级别”,web

若是你想修改spring log的默认级别能够在application.properties spring


logging.level.root=WARN
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR

若是你想看debug信息,你也能够这样:编程

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

注意:固然若是全都是debug级别的话,启动的速度会稍微慢点,由于会线程阻塞住进行log输出api


自定义输出


经过在classpath下添加一个banner.txt或设置pring.banner.location来指定相应的文件能够改变启动过程当中打印的banner。若是这个文件有特殊的编码,你可使用banner.encoding设置它(默认为UTF-8)。若是文件不是UTF-8的编码,您能够设置spring.banner.charset。除了文本文件,你也能够添加一个banner.gifbanner.jpgbanner.png图片,或设置spring.banner.image.location属性。图片会转换为字符画(ASCII art)形式,并在全部文本banner上方显示。app

在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.0.5.RELEASE
${spring-boot.formatted-version} 当前Spring Boot被格式化后的版本号(被括号包裹且以v做为前缀), 用于显示,例如(v2.0.5.RELEASE)
${Ansi.NAME}(或${AnsiColor.NAME},${AnsiBackground.NAME}, ${AnsiStyle.NAME}) NAME表明一种ANSI编码,具体详情查看AnsiPropertySource
${application.title} MANIFEST.MF中声明的应用title,例如Implementation-Title: MyApp会打印MyApp

 若是想以编程的方式产生一个banner,可使用SpringBootApplication.setBanner(…)方法,并实现org.springframework.boot.Banner接口的printBanner()方法。

你也可使用spring.main.banner-mode属性决定将banner打印到何处,System.outconsole),配置的logger(log)或都不输出(off)。

打印的banner将注册成一个名为springBootBanner的单例bean。

 YAML会将off映射为false,若是想在应用中禁用banner,你须要确保off添加了括号:

spring:
    main:
        banner-mode: "off"


流式(Builder)模式启动SpringBoot


若是须要建立一个分层的ApplicationContext(多个具备父子关系的上下文),或只是喜欢使用流式(fluent)构建API,那你可使用SpringApplicationBuilder。 SpringApplicationBuilder容许你以链式方式调用多个方法,包括parent和child方法,这样就能够建立多层次结构,例如:

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


SpringBoot事件



除了常见的Spring框架事件,好比ContextRefreshedEventSpringApplication也会发送其余的application事件。

应用运行时,事件会如下面的次序发送:

  1. 在运行开始,但除了监听器注册和初始化之外的任何处理以前,会触发一个ApplicationStartingEvent

  2. 在Environment将被用于已知的上下文,但在上下文被建立前,会出发一个ApplicationEnvironmentPreparedEvent

  3. 在refresh开始前,但在bean定义已被加载后,会触发一个ApplicationPreparedEvent

  4. 在context被刷新以后,可是在任何应用程序和命令行运行者被调用以前,会出发ApplicationStartedEvent 

  5. 在任何应用程序和命令行运行程序被调用以后,都会触发一个ApplicationReadyEvent。它代表应用程序已经准备好服务请求。

  6. 若是在启动时出现异常,则会触发ApplicationFailedEvent 

 一般不须要使用application事件,但知道它们的存在是有用的(在某些场合可能会使用到),好比,在Spring Boot内部会使用事件处理各类任务。

Application Event是经过使用Spring Framework的事件发布机制发送的。这种机制的一部分确保在任何祖先上下文中向侦听器发布给侦听器的事件也被发布给侦听器。所以,若是您的应用程序使用SpringApplication实例的层次结构,侦听器可能会收到同一类型的应用程序事件的多个实例。

为了让您的侦听器可以区分其上下文的事件和后代上下文的事件,它应该请求注入它的应用程序上下文,而后将注入的上下文与事件的上下文进行比较。经过使用@autowired,能够经过实现ApplicationContextAware来注入,或者,若是监听器是bean的话。


 有些事件其实是在ApplicationContext建立前触发的,因此你不能在那些事件(处理类)中经过@Bean注册监听器,只能经过SpringApplication.addListeners(…)SpringApplicationBuilder.listeners(…)方法注册。若是想让监听器自动注册,而不关心应用的建立方式,你能够在工程中添加一个META-INF/spring.factories文件,并使用org.springframework.context.ApplicationListener做为key指向那些监听器,以下:

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

或者能够写在代码里:

@SpringBootApplication
public class Application {

   public static void main(String[] args) {

      SpringApplication app = new SpringApplication(Application.class);
      app.addListeners(new ApplicationEnvironmentPreparedEventListener());
      app.addListeners(new ApplicationFailedEventListener());
      app.run(args);

   }
}


在SpringBoot中获取启动参数


若是须要获取传递给SpringApplication.run(…)的应用参数,你能够注入一个org.springframework.boot.ApplicationArguments类型的bean。ApplicationArguments接口即提供对原始String[]参数的访问,也提供对解析成optionnon-option参数的访问:

import org.springframework.boot.*
import org.springframework.beans.factory.annotation.*
import org.springframework.stereotype.*

@Component
public class MyBean {

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

}

启动加载数据 CommandLineRunner或者ApplicationRunner



实际应用中,咱们会有在项目服务启动的时候就去加载一些数据。 ,Spring Boot 为咱们提供了一个方法,经过实现接口 CommandLineRunner 来实现。

建立实现接口 CommandLineRunner 的类

@Component
public class InitDataRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.err.println("InitDataRunner ....");
    }
}


若是某些定义的CommandLineRunnerApplicationRunner beans须要以特定的顺序调用,你能够实现org.springframework.core.Ordered接口或使用org.springframework.core.annotation.Order注解。


Application退出


个SpringApplication都向JVM注册一个关机钩子,以确保ApplicationContext在出口处优雅地关闭。可使用全部标准的Spring生命周期回调(如一次性的sablebean接口或@pre销毁注释)。

此外,bean还能够实现org.springframework.boot。若是他们但愿在springapplication.exit()被调用时返回一个特定的出口代码,ExitCodeGenerator接口。而后,这个退出码能够被传递给system.exit(),以做为状态码返回它.

@Component
public class MyExitCodeGenerator implements ExitCodeGenerator {

    @Override
    public int getExitCode() {
        System.err.println("----9999------ shutdown--------");
        return 999;
    }

}
@RestController
public class HelloController {

    @Autowired
    private ApplicationContext applicationContext;

    @GetMapping("/stop")
    public String stop() {
        // 加上本身的权限验证,密码啊,加密啊,时间啊啊等等
        SpringApplication.exit(applicationContext);
        return "ok";
    }

转载请注明出处:联盟兔

原文:http://syllabus.lianmengtu.top/

相关文章
相关标签/搜索