先上结论:自定义的注解没加元注解@Retention,默认的是CLASS运行时通过反射是拿不到的,设置为runtime就解决了。
mybatis自动生成接口实现的扫描注解@MapperScan可以自定义自己的注解,这样的话就可以在多数据源情境下来区分扫描不同的包了,这里不介绍细节仅仅贴下代码实例。
@Configuration
@MapperScan(basePackages = "xxx.dao",sqlSessionFactoryRef = "oneSqlSessionFactory",annotationClass = OneMapper.class)
public class OneDataSourceConfig {
@Value("${mybatis.config-location}")
private String configLocation;
@Bean(initMethod = "init",destroyMethod = "close")
@ConfigurationProperties("spring.datasource.druid.one")
public DruidDataSource oneDataSource(){
DruidDataSource dataSource = new DruidDataSource();
return dataSource;
}
@Bean
public DataSourceTransactionManager oneTransactionManager() {
return new DataSourceTransactionManager(oneDataSource());
}
@Bean
public SqlSessionFactory oneSqlSessionFactory(@Qualifier("oneDataSource") DataSource oneDataSource,ApplicationContext ctx)
throws Exception {
String[] typeAliasesPackages = new String[]{
};
final SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setConfigLocation(ctx.getResource(configLocation));
factory.setVfs(SpringBootVFS.class);
factory.setDataSource(oneDataSource);
factory.setTypeAliasesPackage(StringUtils.join(typeAliasesPackages,","));
factory.setMapperLocations(ctx.getResources("classpath:mybatis/**/*One.xml"));
return factory.getObject();
}
}
@Configuration
@MapperScan(basePackages = "xxx.dao",sqlSessionFactoryRef = "sqlSessionFactory",annotationClass = Mapper.class)
public class DataSourceConfig {
@Value("${mybatis.config-location}")
private String configLocation;
@Primary
@Bean(initMethod = "init",destroyMethod = "close")
@ConfigurationProperties("spring.datasource.druid.main")
public DruidDataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
return dataSource;
}
@Bean
@Primary
public DataSourceTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
@Bean
@Primary
public SqlSessionFactory sqlSessionFactory(DataSource dataSource, ApplicationContext ctx)
throws Exception {
String[] typeAliasesPackages = new String[]{
};
final SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setConfigLocation(ctx.getResource(configLocation));
factory.setVfs(SpringBootVFS.class);
factory.setDataSource(dataSource);
factory.setTypeAliasesPackage(StringUtils.join(typeAliasesPackages,","));
factory.setMapperLocations(ctx.getResources("classpath:mybatis/**/*Mapper.xml"));
return factory.getObject();
}
}
开始的时候总是第二个数据源不能自动注入bean成功,报@Autowired的依赖错误,发现代码没什么问题,网上也没找到什么答案,没办法找到源码debug一点点看,发现获取类信息的时候用我自定义的注解的类没拿到信息,再回去看注解,发现什么元注解都没加,而引起原因的就是@Retention注解,默认的是CLASS运行时通过反射是拿不到的。
@MapperScan主要的注入逻辑都在MapperScannerConfigurer类中
@Retention注解
Reteniton的作用是定义被它所注解的注解保留多久,一共有三种策略,定义在RetentionPolicy枚举中
public enum RetentionPolicy {
SOURCE,
CLASS,
RUNTIME
}
1.SOURCE
被编译器忽略
2.CLASS
注解将会被保留在Class文件中,但在运行时并不会被VM保留。这是默认行为,所有没有用Retention注解的注解,都会采用这种策略。
3.RUNTIME
保留至运行时。所以我们可以通过反射去获取注解信息。