[SB框架]SpringBoot一些技巧

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. 運行流程
    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容器啓動成功後的最後一步回調
使用步驟

  1. 寫一個類實現CommandLineRunner接口
  2. 通過@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參數數字最大,最早執行。

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