編程實戰篇——Spring Boot 自動配置實現

基於Spring Boot自動配置的思想封裝起來,使其餘Spring Boot項目引入後可以進行快速配置。mysql

AutoConfigurationspring

Spring Boot的一個重要特性就是提供了各類各樣的AutoConfiguration。例如DataSourceAutoConfiguration。這樣咱們只須要在配置文件中進行以下配置:sql

spring:
  datasource:
    url: jdbc:mysql://xxxxxxxxxxx/realname
    username: xxxxx
    password: xxxxx
    driverClassName: com.mysql.jdbc.Driver複製代碼

Spring Boot就會在容器中按照咱們的配置的信息注入一個DataSource。那麼Spring boot是怎麼知道 DataSourceAutoConfiguration是自動配置類?其實很簡單:app

  1. Spring Boot在啓動時候會讀取文件Classpath:META-INFspring.factories的全部文件,spring.factories實際上是一個properties的文件,便是 key = value的形式。
  2. 獲取spring.factories中

    key=org.springframework.boot.autoconfigure.EnableAutoConfiguration配置項的值(類的全路徑)做爲Spring啓動配置類ide

Spring Boot 這種用「約定優於配置」思想能夠大大的簡化配置代碼的編寫。那麼,咱們就能夠按照上面的套路來編寫一個Spring Boot的自動配置類吧微服務

實戰

如今有一個配置Bean——PrintAfterInitBean,須要Spring容器啓動之後,打印一次消息,而且該消息的內容是在配置文件中定義編碼

第一步,編寫配置Bean——PrintAfterInitBean

代碼以下,由於只是一個簡單例子,這裏的配置Bean其實能夠是其餘任何複雜配置Bean,例如DataSource。每每一個公共包須要多個這樣配置Bean才能完成其配置。url

public class PrintAfterInitBean implements InitializingBean {
    private String message;

    public void afterPropertiesSet() throws Exception {
        System.out.println(message);
    }
    //setter getter
}複製代碼

第二步,建立一個AutoConfiguration。

若是搜索Spring Boot下面的類,你會發現其實有不少名字形如xxxAutoConfiguration的類,這些類都是Spirng Boot爲咱們作的一些快捷配置類。
spa

建立一個TestAutoConfig,做爲一個自動配置類。code

@Configuration
public class TestAutoConfig {

    @Bean
    @ConfigurationProperties(prefix = "init")
    @ConditionalOnMissingBean(PrintAfterInitBean.class)
    @ConditionalOnProperty(prefix = "init",value = "message") 
    public PrintAfterInitBean printAfterInitBean() {
        return new PrintAfterInitBean();
    }
}複製代碼
  • @ConfigurationProperties 是Spring Boot提供的方便屬性注入的註解,功能其實和@Value相似
  • @ConditionalOnMissingBean 表示當BeanFactory中沒有PrintAfterInitBean類型的Bean纔會建立,不然就會忽略這個Bean。這個就是上圖中所謂的【知足自動配置條件】,同理的,ConditionalOnProperty表示當存在配置前綴爲init,配置值爲message的配置的時候,纔會生效。@ConditionalOnXXX 系列的註解都是爲了在自動配置中,不侵入用戶的配置。

第三步,建立spring.factories

在resources下面建立META-INF/spring.factories, 而後在文件中把第二步的類配置進去:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.xxx.TestAutoConfig複製代碼

這樣就完成一個Spring Boot自動配置,若是存在init.message的配置,那麼Spring Boot啓動的時候就會打印init.message配置對應值。

小結

Spring Boot的自動配置爲咱們在編寫一個重複的配置代碼(或者xml文件)中提供一套簡便的部署方式,這樣當用其餘spring boot的項目依賴咱們jar時候,配置起來就十分方便拉。從代碼能夠看出,Spring Boot 其實並無什麼實質性的創新,只是把一些「約定」的配置信息轉換原來經過代碼或xml實現的配置。

經常使用註解

@ConditionalOnXXX

前面已經介紹過,@ConditionalOnXXX 系列主要是自動配置是否生效,例如ConditionalOnClass,就是在某個Class存在的狀況下才生效。這一系列的註解經過名字就知道用法,所以再也不作過多的介紹。@ConditionalOnXXX 能夠用於類名和方法名上。

  • 用於類名上,要和 @Configuration一塊兒使用,決定該配置類是否生效
  • 用於方法名上(注:前提是該方法也是一個配置類,即有@Configuration註解),結合@Bean一塊兒使用,判斷該@Bean是否生成

用DataSourceAutoConfiguration 代碼來講明。

@Configuration
// 注:當存在DataSource.class 和 EmbeddedDatabaseType.class 存在的狀況下,該配置路徑才生效
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class })
public class DataSourceAutoConfiguration {

    private static final Log logger = LogFactory
            .getLog(DataSourceAutoConfiguration.class);

    @Bean
         // 注:只有當BeanFactory中不存在DataSourceInitializer類的Bean的狀況下才會有效
    @ConditionalOnMissingBean
    public DataSourceInitializer dataSourceInitializer(DataSourceProperties properties,
            ApplicationContext applicationContext) {
        return new DataSourceInitializer(properties, applicationContext);
    }
...
}複製代碼

自動配置的核心思想就是不侵佔用戶的代碼,相似於「你有就用你的,你沒有我就幫你作默認設置」。所以,咱們在本身開發一個自動配置類的時候也須要注意這一點,否則就有點霸王條款的感受。

@EnableConfigurationProperties

通常咱們的自動配置類都會依賴外部的配置信息,而這些外部的配置信息能夠封裝成一個類,相似上面DataSourceAutoConfiguration中的@EnableConfigurationProperties(DataSourceProperties.class),DataSourceProperties類就是用來保存DataSource相關的配置信息。「約定優於配置」的思想就在這裏體現,若是配置信息是以spring.datasource爲前綴,那麼配置信息都會注入到DataSourceProperties類中,供DataSourceAutoConfiguration使用。

@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties
        implements BeanClassLoaderAware, EnvironmentAware, InitializingBean {

        ...
    private Class<? extends DataSource> type;
    private String driverClassName;
    private String url;
    private String username;
    private String password;
        ...

}複製代碼

@AutoConfigureAfter

在一些特殊的狀況下,一些自動配置類須要在某一些其餘配置類後進行,例如依賴另一個自動配置的Bean,這個時候就@AutoConfigureAfter來進行約束。

@Import

@Import也是比較常見的一個配置註解,主要用於引入其餘配置類,可是另一個比較有用的配置就是引入一個ImportBeanDefinitionRegistrar接口,而這個就是用於使用在ApplicationContext初始化階段的時候,註冊(register)一些BeanDefinition。固然常見的Bean是能夠經過@Bean註解注入,可是一些Spring ApplicationContext啓動過程當中用的到一些Bean則不行,例如BeanPostProcessor,BeanFactoryPostProcessor。

總結

Spring Boot 核心思想就是「約定優於配置」思想,在建立一個微服務的時候有不少得天獨厚的優點,每每只用短短几行配置,就能夠部署一個應用。這樣在編碼更多的是一些業務層面。而若是咱們本身編寫的一個公共包也可以經過短短几行配置便可以完成,不只僅是代碼層面的減小,更是接入方來講是一種「一站式服務」體驗。固然前提是接入方也是使用的Spring Boot。

本文做者:慕容慍斐

閱讀原文

本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索