1. 程式人生 > >不學無數——SpringBoot入門Ⅶ

不學無數——SpringBoot入門Ⅶ

SpringBoot

1.建立自己的Auto-configuration

無論是在公司中你想開發自己的一套框架,定製一些東西,或者是在開源網站中分享自己做的一些東西。你可能想要開發屬於自己的Auto-configuration。Auto-configuration的類能夠捆綁到外部的jar包中,並且被SpringBoot進行使用。例如我們經常使用的@Autowire註解會自動的注入一個例項到Spring的容器中,這時我們被注入進來的類必須有個註解進行標註,例如:@Service、@Controller等等。但是對於在jar包中的類的話,考慮的需要多一些,例如需要考慮在注入時我會依賴到誰,誰先進行注入等等。

Auto-configuration通常是和starter聯絡起來的,一個官網提供的小例子展示瞭如何一步一步建立屬於自己的starter

1.1 理解Auto-configured類

在底層程式碼中,Auto-configured是被@Configuration註解的類實現的。另外@Conditional註解被用來限制什麼時候Auto-configured應該被應用。通常來說,Auto-configured的類使用@ConditionalOnClass@ConditionalOnMissingBean這兩個註解,這是為了確保 auto-configuration 只在一些相關的類生效以後才會載入@Configuration類。

你也可以通過瀏覽SpringBoot-autoConfigure由Spring提供的@Configuration類。

1.2 Auto-configuration的目錄結構

SpringBoot會檢查所有jar包中的META-INF/spring.factories檔案,在這個檔案中應該列出了key是EnableAutoConfigurationvalue是想要配置的類,例如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.mycorp.libx.autoconfigure.LibXAutoConfiguration,\
com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration

當然也可以使用@AutoConfigureAfter@AutoConfigureBefore兩個註解進行標識想要哪個類進行先載入。例如想要提供一個特定的web配置,那麼你的類應該在WebMvcAutoConfiguration之後載入。

如何想要auto-configurations的類進行順序的載入,那麼可以使用@AutoConfigureOrder註解進行排序。

Auto-configurations僅僅能夠被這種方式進行載入,實際上,他們不會被包掃描進行載入。

1.3 Condition註解

SpringBoot利用@Condition註解來確定是不是要建立Bean例項

在所開發的對外封裝jar包中可能會使用一個或者多個的@Condition註解在自動配置的類中。@ConditionalOnMissingBean註解會覆蓋掉你的預設配置。

SpringBoot包括許多的@Conditional的註解,你能夠重複使用它在類中或者單獨的@Bean方法上。這些註解包括

  • Class Conditions
  • Bean Conditions
  • Property Conditions
  • Resource Conditions
  • Web Application Conditions

1.3.1 Class Conditions

  • @ConditionalOnClass: 某個class位於類路徑上,才會例項化一個Bean。該註解的引數對應的類必須存在,否則不解析該註解修飾的配置類。這個很有用的,比如不同的jar包之間有依賴,如果依賴的類不存在的話,那麼就會直接跳過,不會報錯。
  • @ConditionalOnMissingBean:僅僅在當前上下文中不存在某個物件時,才會例項化一個Bean。該註解表示,如果存在它修飾的類的bean,則不需要再建立這個bean,可以給該註解傳入引數例如@ConditionOnMissingBean(name = "example"),這個表示如果name為“example”的bean存在,這該註解修飾的程式碼塊不執行

1.3.2 Bean Conditions

  • @ConditionalOnBean:僅僅在當前上下文中存在某個物件時,才會例項化一個Bean
  • @ConditionalOnMissingBean:僅僅在當前上下文中不存在某個物件時,才會例項化一個Bean

舉例如下:

@Configuration
public class MyAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean
	public MyService myService() { ... }

}

1.3.3 Property Conditions

  • @ConditionalOnProperty:這個註解能夠控制某個configuration是否生效。具體操作是通過其兩個屬性name以及havingValue來實現的,其中name用來從application.properties中讀取某個屬性值,如果該值為空,則返回false;如果值不為空,則將該值與havingValue指定的值進行比較,如果一樣則返回true;否則返回false。如果返回值為false,則該configuration不生效;為true則生效。

1.3.4 Resource Conditions

  • @ConditionalOnResource註解允許只有在特定資源出現時配置才會生效。資源可以使用常見的Spring約定命名,例如file:/home/user/test.dat。

1.3.5 Web Application Conditions

  • @ConditionalOnWebApplication和@ConditionalOnNotWebApplication兩個註解會根據應用是否為一個Web應用而使配置生效。

2. 一個自動配置的小例子

2.1 建立一個接受配置屬性的類

如果對於如何用java實體類進行接受配置檔案的屬性不明白的,可以參考我的文章不學無數——SpringBoot入門Ⅲ,裡面有詳細講解。


@ConfigurationProperties("acme")
@Validated
public class AcmeProperties {
	private boolean enabled;
	@NotNull(message = "不能weikong ")
	private String remoteAddress;

	public boolean isEnabled() { return enabled; }

	public void setEnabled(boolean enabled) { this.enabled=enabled; }

	public String getRemoteAddress() { return remoteAddress; }

	public void setRemoteAddress(String remoteAddress) { this.remoteAddress=remoteAddress; }

}

2.2 建立配置屬性的類

這裡只是簡單的舉個配置屬性的例子: 例如在這裡可以進行配置資料庫的事務。然後在動態建立資料來源的時候可以判斷這個類是否建立然後建立資料來源。

即這個類是一個作為判斷依據的類

public class AcmeService {
    private String msg;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    @Override
    public String toString() {
        return "AcmeService{" +
                "msg='" + msg + '\'' +
                '}';
    }
}

2.3 建立自動配置的類

@ConditionalOnClass該註解在之前已經講過,這裡的意思就是AcmeService類在路徑中已經存在以後才會解析配置類。@ConditionalOnMissingBean方法上的註解我們上面也解釋過了,在這的意思就是在容器中沒有AcmeService物件時才會例項化此Bean。


@Configuration
@ConditionalOnClass(AcmeService.class)
@EnableConfigurationProperties(AcmeProperties.class)
public class AcmeAutoConfiguration {

    private final AcmeProperties acmeProperties;

    public AcmeAutoConfiguration(AcmeProperties acmeProperties) {
        this.acmeProperties = acmeProperties;
    }

    @Bean
    @ConditionalOnMissingBean(AcmeService.class)
    public AcmeService getAcmeService(){
        AcmeService acmeService=new AcmeService();
        acmeService.setMsg(acmeProperties.toString());
        return acmeService;
    }
}

2.4 註冊配置

resources-META-INF資料夾下建立spring.factories檔案,裡面寫入自動配置類的路徑

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.FirstSpringBoot.Configuration.AcmeAutoConfiguration

2.5 開始使用

因為我們建立的自動配置是要供別人使用的,只對外提供配置的屬性值,所以我們將我們寫的自動配置的一系列類進行打jar包,另一個專案引用過後只需要在配置檔案中配置我們對外提供的配置屬性進行配置以後就可以使用我們自動配置類提供的功能了。這也正符合了SpringBoot的開箱即用的觀點。