天天看點

整合SpringBoot再也不用搜配置了!!!

導讀

  • 最近陳某公司有些忙,為了保證文章的高品質可能要兩天一更了,在這裡陳某先說聲不好意思了!!!
  • 昨天有朋友問我SpringBoot如何整合Redis,他說百度谷歌搜尋了一遍感覺不太靠譜。我頓時驚呆了,原來你們整合SpringBoot都是上網搜尋配置的?
  • 今天陳某就讓小夥伴擺脫配置的困擾,不要再去上網找了,嘗試自己配置一下,成就感會更強哈!!!

開撸

  • 陳某前面寫過兩篇文章,分别是SpringBoot實作多資料源的動态切換、SpringBoot整合多資料源的巨坑,陳某把這兩篇文章作為引子,教教SpringBoot自動配置類的套路。
  • 陳某打算從這幾個問題深入去講述如何去整合SpringBoot。

1、資料源的參數如何配置?你是怎麼知道在yml屬性檔案中需要設定什麼屬性?

  • 陳某使用的是阿裡的DruidDataSource,SpringBoot整合任何東西的第一步都需要從自動配置類入手,如下:
@Configuration
@ConditionalOnClass(DruidDataSource.class)
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties({DruidStatProperties.class, DataSourceProperties.class})
@Import({DruidSpringAopConfiguration.class,
    DruidStatViewServletConfiguration.class,
    DruidWebStatFilterConfiguration.class,
    DruidFilterConfiguration.class})
public class DruidDataSourceAutoConfigure {}
           
  • @EnableConfigurationProperties

    結合

    @ConfigurationProperties

    會使某個屬性配置類生效,可以直接在application.properties配置。那麼Druid的參數如何配置,肯定是在

    DruidStatProperties

    DataSourceProperties

    這個類中了。這裡就不再詳細看了,請讀者自己檢視。
  • 這裡總結第一條:SpringBoot整合任何東西,幾乎全部需要配置的屬性都在自動配置類上或者

    @Import

    注入的配置類上的

    @EnableConfigurationProperties

    注解中指定的屬性類。

2、為什麼設定了動态資料源需要重新整合Mybatis,mybatis-spring-boot-starter這個啟動器不是什麼都整合好了嗎,隻要在yml檔案中配置即可嗎?

  • 同樣的套路,一切答案都在自動配置類中,源碼如下:
@org.springframework.context.annotation.Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisAutoConfiguration implements InitializingBean {}
           
  • 顯然易見,多麼紮眼的一個注解

    @ConditionalOnSingleCandidate

    ,什麼意思?該注解的意思是IOC容器中有單個指定的候選對象該配置類才會生效,那麼即是容器中隻有一個DataSource類型的對象

    MybatisAutoConfiguration

    才會生效,但是我們在整合動态資料源的時候是指定了多個DataSource并且注入了IOC容器中了,是以Mybatis自動配置類中所有的内容都不會生效,當然需要自己重新配置Mybatis了。
  • SpringBoot中注解類似

    @Conditionalxxx

    注解有很多,全部都是判斷配置在指定條件下才會生效。更多的注解如下圖,具體什麼意思,不是本文介紹的重點,自己看文檔:
整合SpringBoot再也不用搜配置了!!!
  • 總結第二條:SpringBoot整合任何東西,一定要注意

    @Conditionalxxxx

    注解,判斷配置類中各種配置生效的條件。

3、 為什麼還要Java config方式重新配置事務管理器呢,不是使用@EnableTransactionManagement直接開啟了嗎,不用配置即可使用嗎?

  • 老套路,自動配置類搞起,源碼如下:
@Configuration
@ConditionalOnClass({ JdbcTemplate.class, PlatformTransactionManager.class })
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceTransactionManagerAutoConfiguration {
    
    //靜态配置類,隻有IOC容器中隻有一個候選對象DataSource,這個配置類才生效
    @Configuration
	@ConditionalOnSingleCandidate(DataSource.class)
	static class DataSourceTransactionManagerConfiguration {

		private final DataSource dataSource;

		private final TransactionManagerCustomizers transactionManagerCustomizers;

		DataSourceTransactionManagerConfiguration(DataSource dataSource,
				ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
			this.dataSource = dataSource;
			this.transactionManagerCustomizers = transactionManagerCustomizers.getIfAvailable();
		}

		@Bean
		@ConditionalOnMissingBean(PlatformTransactionManager.class)
		public DataSourceTransactionManager transactionManager(DataSourceProperties properties) {
			DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(this.dataSource);
			if (this.transactionManagerCustomizers != null) {
				this.transactionManagerCustomizers.customize(transactionManager);
			}
			return transactionManager;
		}

	}
}
           
  • 從自動配置類的源碼也是顯然易見的看到

    @ConditionalOnSingleCandidate

    ,不多解釋了,和第二個問題一樣,隻有ioc容器中隻有一個候選對象DataSource這個配置類才會生效,顯然多資料源肯定有多個,不多解釋了。
  • 此問題總結同第二條,注意

    @conditionalxxx

    注解。

4、 為什麼在動态資料源上加入一個

@Primary

之後,事務管理器和Mybatis的整合不用重新寫呢,可以直接使用自動配置呢?

  • 第二和第三個問題都回答了,大緻解決思路小夥伴應該都知道了。
  • 想要解決這個問題,必須了解

    @ConditionalOnSingleCandidate

    這個注解的真正作用,檢視文檔如下:
Conditional that only matches when a bean of the specified class is already contained in the BeanFactory and a single candidate can be determined.
The condition will also match if multiple matching bean instances are already contained in the BeanFactory but a primary candidate has been defined; essentially, the condition match if auto-wiring a bean with the defined type will succeed.
The condition can only match the bean definitions that have been processed by the application context so far and, as such, it is strongly recommended to use this condition on auto-configuration classes only. If a candidate bean may be created by another auto-configuration, make sure that the one using this condition runs after.
           
  • 小夥伴看見英文就懵逼了,大緻意思就是:如果BeanFactory中有單個候選對象則條件比對或者存在多個候選條件但是存在一個主候選者條件也會比對。
  • 好了,明白了吧,主候選者,不就是

    @Primary

    注解嘛,多麼so easy。隻要給動态資料源加上@Primary注解來指定為主候選者,一切問題迎刃而解。

總結

  • 通過上面問題的分析,相信小夥伴大緻知道了如何和SpringBoot整合,如何正确的指定配置了。陳某這裡總結一下。
    • 找到對應的自動配置類,不知道的配置類是什麼?大緻的配置類的名稱都是

      xxxAutoConfiguration

    • 注意

      @Import

      注解,該注解往往是注入配置類或者直接注入一個對象,具體看官方文檔的用法。
    • 注意自動配置類或者

      @Import

      引入的配置類上标注的

      @EnableConfigurationProperties

      注解,往往該注解指定的屬性配置類就是需要在application.properties檔案中需要指定的配置。
    • @Conditionalxxxx

      注解,該類注解明确指定了配置類或者注入Bean的條件,隻有在其特定的條件下配置類才會生效、注入的Bean才會生效(@Bean)。
    • @AutoConfigurexxx

      ,該注解會指定自動配置類生效的順序,這個很重要!!!!
  • 如果覺得作者寫得好,點個推薦關注一下喲!!!
    整合SpringBoot再也不用搜配置了!!!

如果覺得作者寫的好,有所收獲的話,點個關注,推薦一波,文章首發于公衆号!!!