【熵增教育】SpringApplication你不知道的那些事!——熵增學院

SpringApplication類提供了一種快捷方式來啓動java程序,可以從main()方法啓動Spring應用。有沒有覺得很簡單,很方便。

接下來將帶你學習一些其他的一些關於SpringApplication東東


SpringBoot啓動

SpringApplication類提供了一種快捷方式,用於從main()方法啓動Spring應用。多數情況下,你只需要將該任務委託給SpringApplication.run靜態方法:

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

當應用啓動時,你應該會看到類似下面的東西:

 .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: 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節所述,“日誌級別”,

如果你想修改spring log的默認級別可以在application.properties 

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輸出


自定義輸出

通過在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上方顯示。

在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/

轉載請註明出處:聯盟兔

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章