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,則可以使用SpringApplicationBuilder。SpringApplicationBuilder允許使用方法鏈的方式來創建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
應用程序運行時事件按以下順序發送:
- ApplicationStartingEvent:程序啟動但未執行任何處理(不包括listeners和initializers注冊);
- ApplicationEnvironmentPreparedEvent:Environment被上下文使用但是上下文未創建前;
- ApplicationContextInitializedEvent:ApplicationContext准備完成 並且 調用ApplicationContextInitializers,但bean定義被加載之前;
- ApplicationPreparedEvent:bean定義被加載后 但 應用上下文未刷新完成前;
- ApplicationStartedEvent:上下文刷新完成,但 應用程序和命令行程序被吊起之前;
- ApplicationReadyEvent:所有應用程序和命令行啟動程序被吊起之后,將發送一個ApplicationReadyEvent。 它指示該應用程序已准備就緒,可以處理請求。
- ApplicationFailedEvent:程序啟動出現異常;
上述列表中的SpringApplicationEvents僅僅是和SpringApplication綁定的;除了這些,介於ApplicationPreparedEvent和ApplicationStartedEvent之間的event還有下列:
- ContextRefreshedEvent:當ApplicationContext刷新時;
- 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.
