SpringBoot 開發總結思考(二)

1、SpringBoot 自動配置(裝配)

  • 原理是什麼?

https://blog.csdn.net/u014745069/article/details/83820511

  • 爲什麼要有?

2、SpringBoot 是如何把一些庫加入到IOC中的?

@Component、@Configuration 適用於自定義業務,而SpringBoot考慮的是如何把第三方以及自己的庫加入到IOC中

@SpringBootApplication 就是一個超級大的配置類,其中包含的註解會分解小的配置類模塊

3、@EnableAutoConfiguration :SpringBoot中最核心的註解

主要作用就是爲了加載N多的Bean,然後將其放入IOC中

部分的屬性是寫在配置文件中的,允許從配置文件中更改配置的Bean的屬性等

必須要能把Bean加入到IOC中

@Import(AutoConfigurationImportSlector.class)

AutoConfigurationImportSlector 中有一個非常重要的方法:selectImports

  • 核心方法,用於加載第三方配置類

要加載的所有的配置都在spring.factories中記錄,SpringBoot 會讀取該文件所有的Bean,然後再將這些Bean加入到IOC中

spring.factories 中的配置類與SpringBoot的自動加載機制是如何關聯起來的?

  • 核心就是  .factories 配置文件

4、第三方的Bean也加了 @Configuration,爲什麼還要通過  @EnabledAutoConfiguration +  .factories 的機制加入到IOC中?

如果只是加了 @Configuration ,相當於直接把源碼加入到了IOC中

第三方SDK也直接將源碼加入到IOC中嗎?顯然不可能

5、以Enabled 開頭的註解,被稱之爲模塊裝配

模塊裝配:假設要注入MongoDB,那麼就加上@Configuration註解,有可能一個配置類沒辦法解決某個方向的問題,往往是很多@Configuration的類組合在一起

SpringBoot是使用Enable註解,然後再通過@import導入Selector,通過Selector讀取  .factories 文件,最終加載的Configuration

6、@EnableAutoConfiguration 最終還是要加載@Configuration

比起自定義@Configuration ,還多了一步@Import的Selector

 

7、

修改前面的 HeroConfiguration 類,並將所有的@Component去掉

@Configuration
public class HeroConfiguration {

    //@Bean
    public ISkill diana(){
        return new Diana("Diana", 1);
    }

    @Bean
    public ISkill irelia(){
        return new Irelia();
    }

}

但現在的結構仍然可以自動將HeroConfiguration 加載到IOC中,因爲啓動類的@SpringBootApplication包含了ComponentScan,當前包下的標註了@Component/@Configuration的都會被加入到IOC中

自定義一個 啓動類 LOLApplication,並將啓動類的@SpringBootApplication註解去掉

@ComponentScan
public class LolApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = new SpringApplicationBuilder(LolApplication.class)
                .run(args);

        ISkill iSkill = (ISkill) context.getBean("irelia");

        iSkill.r();

    }

}

使用另一種@Import方式

  • 最簡單的一種方式就是,將配置類傳入到Import中
@Import(HeroConfiguration.class)

此時會報錯,unable to start web service,爲什麼加@ComponentScan就可以?

在默認情況下,上下文會啓動Web服務器,如果不主動關閉Web服務器的模式,它就會自動啓動

之所以加@ComponentScan可以,是因爲該註解會掃描和web服務器相關配置的

但註釋之後使用@Import只是導入了一個配置類,所以很多SpringBoot內置的配置都是沒有導入到IOC中

增加WebApplicationType.NONE  把服務器關閉

@Import(HeroConfiguration.class)
public class LolApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = new SpringApplicationBuilder(LolApplication.class)
                .web(WebApplicationType.NONE)
                .run(args);

        ISkill iSkill = (ISkill) context.getBean("irelia");

        iSkill.r();

    }

}

@Import 第二個用法

  • 傳入的參數增加一個Selector

新增一個Selector:LolConfigurationSelector

public class LolConfigurationSelector implements ImportSelector {

    /**
     * 該接口要求返回一個數組,這個數組是一個字符串類型
     * @param annotationMetadata
     * @return
     */
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        /**
         * 其實還是在返回元類的名字,一次可以導入多個配置類
         */
        return new String[] {HeroConfiguration.class.getName()};
    }


}

更改啓動類 LolApplication

@Import(LolConfigurationSelector.class)
public class LolApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = new SpringApplicationBuilder(LolApplication.class)
                .web(WebApplicationType.NONE)
                .run(args);

        ISkill iSkill = (ISkill) context.getBean("irelia");

        iSkill.r();

    }

}

7、SpringBoot自動裝配的spring.factories文件

新建一個Enable  註解類:EnableLolConfiguration(相當於一個模塊裝配)

元註解需要標註一些註解

@Retention(RetentionPolicy.RUNTIME) :用來修飾註解,是註解的註解
@Target(ElementType.TYPE) : 被描述的註解可以用在什麼地方
@Documented : 表明這個註釋是由 javadoc記錄的
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(LolConfigurationSelector.class)
public @interface EnableLolConfiguration {


}

修改  LolApplication  

@EnableLolConfiguration
public class LolApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = new SpringApplicationBuilder(LolApplication.class)
                .web(WebApplicationType.NONE)
                .run(args);

        ISkill iSkill = (ISkill) context.getBean("irelia");

        iSkill.r();

    }

}

8、@EnableAutoConfiguration 爲什麼要從 .factories 文件讀取?

一個模塊具體要加載哪些配置類,是一個變化的過程。

既然是變化,那麼就應該被隔離到配置文件中

但不是所有在  .factories  文件中的配置都會被導入,所以這些配置文件中的類被稱爲   候選配置類

滿足一定條件之後,配置類纔會被導入到IOC中

AutoConfigurationImportSelector中有一個很重要的方法就是:getCandidateConfigurations(獲取所有的候選配置類名)

9、Java SPI 機制解析

SpringBoot自動裝配機制其實是SPI機制/思想的應用

SPI 機制/思想:

  •  Service Provider Interface (服務發現機制)

SPI 就是應對變化,一個系統中往往會依賴很多模塊,這些模塊又是有各種各樣不同實現方案的,有時候需要靈活的替換實現方案

首先有調用方,再有標準服務接口,服務接口下可能會有很多不同的實現(方案A、方案B),不同的方案遵循標準的服務接口,就可以被調用方調用;換句話說就是

在Java中SPI,等同於基於接口編程。不基於Interface接口編程,無法提供標準服務接口,也無法將衆多方案的具體隱藏在抽象之後

SpringBoot自動加載機制就是SPI機制/思想的衍生

對於一個方案來說,完全可以通過修改 .factories文件去切換不同的配置類,切換不同配置類的實質就是在切換衆多的方案之一

10、再談如何解決變化?

既然有了@Primary、條件註解之後,爲什麼還要有SPI機制/思想?

首先肯定的是,無論是SPI 還是@Primary、條件註解機制,都是爲了解決變化而生

但是兩者關注模塊的細粒度是不一樣的

  • @Primary、條件註解  關注的是類/對象層面的變化,關注的具體/粒度非常小
  • SPI 關注的點非常抽象,是整體解決方案的切換;有時候通過簡單的類替換是沒辦法解決問題的

舉個栗子

  • 裝修的時候將1木質地板換成大理石地板(@Primary、條件註解)
  • 房子的整體裝修風格發生了變化(SPI)

兩者應對變化沒有明顯的界限

11、SpringBoot自動裝配到底做了一件什麼事情?

SpringBoot 較其他框架多出了一個IOC容器,SpringBoot自動裝配真正解決了如何發現這些Bean並把這些配置的Bean要能夠加入到IOC容器中,如果沒有IOC,則需要手動在XML指定

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