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

导读

  • 最近陈某公司有些忙,为了保证文章的高质量可能要两天一更了,在这里陈某先说声不好意思了!!!

  • 昨天有朋友问我SpringBoot如何整合Redis,他说百度谷歌搜索了一遍感觉不太靠谱。我顿时惊呆了,原来你们整合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的参数如何配置,肯定是在DruidStatPropertiesDataSourceProperties这个类中了。这里就不再详细看了,请读者自己查看。

  • 这里总结第一条: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整合任何东西,一定要注意@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,该注解会指定自动配置类生效的顺序,这个很重要!!!!
  • 如果觉得作者写得好,点个推荐关注一下哟!!!

posted @ 2020-03-22 15:10  爱撒谎的男孩  阅读(...)  评论(...编辑  收藏