在写多数据源 starter 的过程中,直接命中了这里的一个小坑. 记录一波.
其实呢,也不算是坑,不过我相信绝大部分使用 SpringBoot 的同学都不太清楚这两者之间的区别.
- EnableAutoConfiguration 开启
SpringBoot的自动装配 - Configuration 将
@Bean注解的方法注入到Spring的IOC容器中.
区别
它们之间的区别不是很大,但是如果不明白的话,在自定义 Starter 的时候还是会出现一点小错误的.
| 功能 | Configuration | EnableAutoConfiguration |
|---|---|---|
| 注入时间 | 优先于Enable | 落后于配置(static除外) |
| 注入方式 | 扫描@Configuration注解 | 获取spring.factories并初始化数据 |
| 注入顺序 | @Order配置先后 | AutoConfigureBefore AutoConfigureAfter 等配置先后 |
auto-configure的目的就是让第三方jar里面的类可以很方便的添加到IOC容器里面去 如果你开发
Starter中遇到了困难,那么得想想是不是适合用Starter来搞. 满不满足方便这两字
失败举例
在自定义多数据源 Starter 中,我使用了如下配置来定义多个数据源.
raycloud.multi.datasource.datasource-properties.first.username=rootraycloud.multi.datasource.datasource-properties.first.password=chenshunraycloud.multi.datasource.datasource-properties.first.url=jdbc:mysql://127.0.0.1:3306/project_manager?useUnicode=true&characterEncoding=utf-8&autoReconnect=trueraycloud.multi.datasource.datasource-properties.first.base-packages=com.raycloud.test.web.firstraycloud.multi.datasource.datasource-properties.first.location-pattern=classpath*:/mapper/first/*.xml#secondraycloud.multi.datasource.datasource-properties.second.username=rootraycloud.multi.datasource.datasource-properties.second.password=chenshunraycloud.multi.datasource.datasource-properties.second.url=jdbc:mysql://127.0.0.1:3306/sentinel?useUnicode=true&characterEncoding=utf-8&autoReconnect=trueraycloud.multi.datasource.datasource-properties.second.base-packages=com.raycloud.test.web.secondraycloud.multi.datasource.datasource-properties.second.location-pattern=classpath*:/mapper/second/*.xml
分别配置了 数据源 first 和 second . 使用以下的格式来进行参数接受.
@ConfigurationProperties(prefix = "raycloud.multi.datasource")public class DataSourcePropertyBean {private final Map<String, PropertyBean> datasourceProperties = new HashMap<>();public Map<String, PropertyBean> getDatasourceProperties() {return datasourceProperties;}@Getter@Setterpublic static class PropertyBean {}}
😌
于是我兴冲冲的启动了一个web应用. 还没有写Controller.
没毛病启动成功.
😣
于是我添加了一个测试的 Controller , 并且在其中注入 FirstMapper 和 SecondMapper . 万万没想到注入失败了.
提示需要一个 FirstMapper 但是没有找到,奇不奇怪,惊不惊喜. 在经历debug和搜索后,我可以肯定的是,web的初始化发生在Enable之前,导致starter的配置还没有初始化完成而Controller已经要初始化了,所以获取不到Mapper.
这里的问题就是没有搞明白 EnableAutoConfiguration 和 Configuration 的顺序, Configuration 的注入发生在 EnableAutoConfiguration 之前.
所以只要使用Configuration来进行配置,然后将mybatis和datasource注入到IOC当中, 注意这里需要将注入Bean和参数进行分离.
详细代码请参考.
SpringBoot 多数据源Starter
