1.隨機端口
爲Spring Cloud的應用實用隨機端口非常簡單,主要有兩種方法:
設置server.port=0,當應用啓動的時候會自動的分配一個隨機端口,但是該方式在註冊到Eureka的時候會一個問題:所有實例都使用了同樣的實例名(如:Lenovo-test:hello-service:0),這導致只出現了一個實例。所以,我們還需要修改實例ID的定義,讓每個實例的ID不同,比如使用隨機數來配置實例ID:
server.port=0
eureka.instance.instance-id=${spring.application.name}:${random.int}
除了上面的方法,實際上我們還可以直接使用random函數來配置server.port。這樣就可以指定端口的取值範圍,比如:
server.port=${random.int[10000,19999]}
由於默認的實例ID會由server.port拼接,而此時server.port設置的隨機值會重新取一次隨機數,所以使用這種方法的時候不需要重新定義實例ID的規則就能產生不同的實例ID了。
2.SpringBoot流程分析
- 運行流程
1. 判斷是不是Web環境
2. 加載所有classpath下面的META-INF/spring.factorties ApplicationContextInitializer
3. 加載所有classpath下面的META-INF/spring.factorties ApplicationListener
4. 推斷main方法所在的類
5. 開始執行run方法
6. 設置java.awt.headless系統變量
7. 加載所有classpath下面的META-INF/spring.factorties SpringApplicationRunnerListener
8. 執行所有SpringApplicationRunnerListener的started方法
9. 實例化ApplicationArguments對象
10. 創建environment
11. 配置environment,主要是把run方法的參數配置到environment中
12. 執行所有SpringApplicationRunnerListener的environmentPrepared方法
13. 如果不是web環境,但是是web的environment,則把這個web的environment轉換長標準的environment
14. 打印banner
15. 初始化applicationContext,如果是web環境,則實例化AnnotationConfigEmbeddedWebApplicationContext對象,否則實例化AnnotationConfigApplicationContext對象
16. 如果beanNameGenerator不爲空,就把beanNameGenerator對象注入到applicationContext裏面去
17. 回調所有的ApplicationContextInitializer方法
18. 執行所有SpringApplicationRunnerListener的contextPrepared方法
19. 依次往spring容器中注入:ApplicationArguments,Banner
20. 加載所有的源到applicationContext裏面去
21. 執行所有SpringApplicationRunnerListener的contextLoaded方法
22. 執行applicationContext的refresh方法,並且調用applicationContext的registerShutdownHook方法
23. 回調,獲取容器中所有的ApplicationRunner,CommandLineRunner接口,然後排序,依次調用
24. 執行所有SpringApplicationRunnerListener的finished方法
3.使用CommandLineRunner
CommandLineRunner是Spring容器啓動成功後的最後一步回調
使用步驟
- 寫一個類實現CommandLineRunner接口
- 通過@Component將它交給容器管理
詳細代碼
@Order(1)
@Component
public class ServerSuccessReport implements CommandLineRunner {;
private Logger logger= LoggerFactory.getLogger(getClass());
@Override
public void run(String... arg0) throws Exception {
logger.info("==================應用程序啓動完成=====================");
logger.info("參數:{}",arg0.getClass());
}
}
@Order
來制定CommandLineRunner 執行順序
package com.springboot.study.course7;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* @author huang
* @PACKAGE_NAME com.springboot.study.course7
* @PROJECT_NAME springboot
* @date 2018/12/25
*/
@Order(2)
@Component
public class ServerSuccessReport2 implements CommandLineRunner {;
private Logger logger= LoggerFactory.getLogger(getClass());
@Override
public void run(String... arg0) throws Exception {
logger.info("==================應用程序啓動時間:{}", LocalDateTime.now().toString());
}
}
通過@Order(param)來控制多個CommandLineRunner實現類的執行順序,param參數數字最大,最早執行。