1. 程式人生 > >如何編寫Spring-Boot自動配置

如何編寫Spring-Boot自動配置

not 做的 mage 沒有 stat oot classname ger 內容

摘要

本文主要介紹如何把一個spring的項目(特別是一些公共工具類項目),基於spring boot的自動配置的思想封裝起來,使其他Spring-Boot項目引入後能夠進行快速配置。

AutoConfiguration

Spring-boot的一個重要特性就是提供了各種各樣的AutoConfiguration。例如DataSourceAutoConfiguration。這樣我們只需要在配置文件中進行如下配置

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

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

  1. spring boot 在啟動時候會讀取文件Classpath:\META-INF\spring.factories的所有文件,spring.factories其實是一個properties的文件,即是 key = value的形式。
  2. 獲取spring.factories中key=org.springframework.boot.autoconfigure.EnableAutoConfiguration配置項的值(類的全路徑)作為Spring啟動配置類

Spring Boot 這種用“約定優於配置”思想可以大大的簡化配置代碼的編寫。那麽,我們就可以按照上面的套路來編寫一個Spring-Boot的自動配置類吧

實戰

現在有一個配置Bean——PrintAfterInitBean,需要Spring容器啟動以後,打印一次消息,並且該消息的內容是在配置文件中定義

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

代碼如下,因為只是一個簡單例子,這裏的配置Bean其實可以是其他任何復雜配置Bean,例如DataSource。往往一個公共包需要多個這樣配置Bean才能完成其配置。

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為我們做的一些快捷配置類。技術分享 創建一個TestAutoConfig,作為一個自動配置類

@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提供的方便屬性註入的註解,[email protected]
  • @ConditionalOnMissingBean 表示當BeanFactory中沒有PrintAfterInitBean類型的Bean才會創建,否則就會忽略這個Bean。這個就是上圖中所謂的【滿足自動配置條件】,同理的,ConditionalOnProperty表示當存在配置前綴為init,配置值為message的配置的時候,[email protected] 系列的註解都是為了在自動配置中,不侵入用戶的配置。

第三步,創建spring.factories

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

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.netease.xxx.xxx.UrsPropertyAutoConfig

這樣就完成一個Spring Boot自動配置,如果存在init.message的配置,那麽spring boot啟動的時候就會打印init.message配置對應值。

小結

Spring Boot的自動配置為我們在編寫一個重復的配置代碼(或者xml文件)中提供一套簡便的部署方式,這樣當用其他spring boot的項目依賴我們jar時候,配置起來就十分方便拉。從代碼可以看出,Spring Boot 其實並沒有什麽實質性的創新,只是把一些“約定”的配置信息轉換原來通過代碼或xml實現的配置。

常用註解

@ConditionalOnXXX

前面已經介紹過,@ConditionalOnXXX 系列主要是自動配置是否生效,例如ConditionalOnClass,就是在某個Class存在的情況下才生效。這一系列的註解通過名字就知道用法,[email protected] 可以用於類名和方法名上。

  • 用於類名上,要和 @Configuration一起使用,決定該配置類是否生效
  • 用於方法名上(註:前提是該方法也是一個配置類,[email protected]),[email protected],[email protected]

用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

一般我們的自動配置類都會依賴外部的配置信息,而這些外部的配置信息可以封裝成一個類,[email protected]Properties(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,[email protected]

@Import

@Import也是比較常見的一個配置註解,主要用於引入其他配置類,但是另外一個比較有用的配置就是引入一個ImportBeanDefinitionRegistrar接口,而這個就是用於使用在ApplicationContext初始化階段的時候,註冊(register)[email protected]解註入,但是一些Spring ApplicationContext啟動過程中用的到一些Bean則不行,例如BeanPostProcessor,BeanFactoryPostProcessor。

總結

Spring Boot 核心思想就是“約定優於配置”思想,在創建一個微服務的時候有很多得天獨厚的優勢,往往只用短短幾行配置,就可以部署一個應用。這樣在編碼更多的是一些業務層面。而如果我們自己編寫的一個公共包也能夠通過短短幾行配置即可以完成,不僅僅是代碼層面的減少,更是接入方來說是一種“一站式服務”體驗。當然前提是接入方也是使用的Spring Boot。

如何編寫Spring-Boot自動配置