SpringBoot中資源初始化加載的幾種方式(看這一片就夠了)

原創不易,如需轉載,請註明出處http://www.javashuo.com/article/p-zqnnuvrr-cx.html,謝謝支持哈!!! html

1、問題

  在平時的業務模塊開發過程當中,不免會須要作一些全局的任務、緩存、線程等等的初始化工做,那麼如何解決這個問題呢?方法有多種,但具體又要怎麼選擇呢?git

2、資源初始化

一、既然要作資源的初始化,那麼就須要瞭解一下springboot啓動過程(這裏大致說下啓動過程,詳細:http://www.javashuo.com/article/p-olctdelk-ex.html

spring容器啓動.png

按照前面的分析,Spring-boot容器啓動流程整體可劃分爲2部分:github

  • 執行註解:掃描指定範圍下的bean、載入自動配置類對應的bean加載到IOC容器。
  • man方法中具體SpringAppliocation.run(),全流程貫穿SpringApplicationEvent(經典的spring事件驅動模型),有6個子類:
    1. ApplicationFailedEvent.class
    2. ApplicationPreparedEvent.class
    3. ApplicationReadyEvent.class
    4. ApplicationStartedEvent.class
    5. ApplicationStartingEvent.class
    6. SpringApplicationEvent.class

二、CommandLineRunner和ApplicationRunner

  由上可知,咱們只要實現這兩個中的任何一個接口即可以完成咱們的資源初始化任務,能夠看到它們的加載是在容器徹底啓動以前。它兩的區別是:前者的run方法參數是String...args,直接傳入字符串,後者的參數是ApplicationArguments,對參數進行了封裝。功能上是同樣的。同時也可使用 @Order註解來實現資源加載的前後順序,值越小,優先級越高。實例以下:spring

@Component
@Order(1)
public class MyCommandLineRunner implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println("...init resources by implements CommandLineRunner");
    }
}

@Component
@Order(2)
public class MyApplicationRunner implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments applicationArguments) throws Exception {
        System.out.println("...init resources by implements ApplicationRunner");
    }
}

三、@PostConstruct

  在具體Bean的實例化過程當中執行,@PostConstruct註解的方法,會在構造方法以後執行,順序爲Constructor > @Autowired > @PostConstruct > 靜態方法,因此這個註解就避免了一些須要在構造方法裏使用依賴組件的尷尬(與之對應的還有@PreDestroy,在對象消亡以前執行,原理差很少)。使用特色以下:segmentfault

  • 只有一個非靜態方法能使用此註解
  • 被註解的方法不得有任何參數
  • 被註解的方法返回值必須爲void
  • 被註解方法不得拋出已檢查異常
  • 此方法只會被執行一次緩存

    @Component
    public Class AAA {    
        @Autowired    
        private BBB b;   
    
        public AAA() {        
            System.out.println("此時b還未被注入: b = " + b);    
        }    
        @PostConstruct    
        private void init() {        
            System.out.println("此時b已經被注入: b = " + b);    
        }
    }

四、InitializingBean

  InitializingBean 是 Spring 提供的一個接口,只包含一個方法 afterPropertiesSet()。凡是實現了該接口的類,當其對應的 Bean 交由 Spring 管理後,當其必要的屬性所有設置完成後,Spring 會調用該 Bean 的 afterPropertiesSet()。在Bean在實例化的過程當中執執行順序爲:Constructor > @PostConstruct > InitializingBean > init-methodspringboot

public class InitSequenceBean implements InitializingBean {   
    
    public InitSequenceBean() {   
       System.out.println("InitSequenceBean: constructor");   
    }   
      
    @PostConstruct  
    public void postConstruct() {   
       System.out.println("InitSequenceBean: postConstruct");   
    }   
      
    public void initMethod() {   
       System.out.println("InitSequenceBean: init-method");   
    }   
      
    @Override  
    public void afterPropertiesSet() throws Exception {   
       System.out.println("InitSequenceBean: afterPropertiesSet");   
    }   
}

五、ApplicationListener

  ApplicationListener 就是spring的監聽器,可以用來監聽事件,典型的觀察者模式。若是容器中有一個ApplicationListener Bean,每當ApplicationContext發佈ApplicationEvent時,ApplicationListener Bean將自動被觸發。這種事件機制都必須須要程序顯示的觸發。其中spring有一些內置的事件,當完成某種操做時會發出某些事件動做。好比監聽ContextRefreshedEvent事件,當全部的bean都初始化完成並被成功裝載後會觸發該事件,實現ApplicationListener 接口能夠收到監聽動做,而後能夠寫本身的邏輯。一樣事件能夠自定義、監聽也能夠自定義,徹底根據本身的業務邏輯來處理。因此也能作到資源的初始化加載! app

@Component
public class DataSourceInitListener implements ApplicationListener<ContextRefreshedEvent> {//ContextRefreshedEvent爲啓動事件
 
    private static final Logger LOGGER = LoggerFactory.getLogger(DataSourceInitListener.class);
 
    @Autowired
    private SystemConfigService systemConfigService;
    @Autowired
    private ItemService itemService;
    @Autowired
    private SystemResultService systemResultService;
 
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if(event.getApplicationContext().getParent() == null) {//判斷是否執行過,執行過則再也不執行
            LOGGER.info("初始化systemConfig數據");
            systemConfigService.initConfig();
            LOGGER.info("初始化返回消息數據");
            systemResultService.initResult();
            LOGGER.info("系統初始化結束...........");
        }
    }
 
}

3、總結

  • 到此一些資源初始化的方法就說的差很少了,其中難免有些錯誤的地方,或者理解有偏頗的地方歡迎你們提出來!

我的博客地址:ide

csdn:https://blog.csdn.net/tiantuo6513post

cnblogs:https://www.cnblogs.com/baixianlong

segmentfault:https://segmentfault.com/u/baixianlong

github:https://github.com/xianlongbai

相關文章
相關標籤/搜索