SpringBootLean 是对springboot学习与研究项目,是根据实际项目的形式对进行配置与处理,欢迎star与fork。
[oschina 地址]
http://git.oschina.net/cmlbeliever/SpringBootLearning
[github 地址]
https://github.com/cmlbeliever/SpringBootLearning
在对Mybatis自动扫描配置中,使用注解配置时,我们只要在@MapperScan中配置我们需要扫描的Mapper位置,大部分情况下是满足需求的。通常配置如下:
@MapperScan(basePackages = { "com.cml.springboot.sample.db" }, sqlSessionFactoryRef = "sqlSessionFactory")
这样MapperScannerRegistrar就会去扫描com.cml.springboot.sample.db包下所有Mapper对象。
但是如果遇到需要动态配置扫描包,就有点麻烦了。
因为MapperScan是无法支持spring占位符功能。因为MapperScan注解功能的实现类MapperScannerRegistrar实现的是ImportBeanDefinitionRegistrar。在对@Configuration注解标记的类配置时,实现占位符功能的PropertyPlaceholderAutoConfiguration还没有开始加载。
作为拓展,那我们就可以自定义MapperScanner,实现接口EnvironmentAware,来添加占位符功能。主要代码也是参照MapperScannerRegistrar,主要是将
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//...省略代码
List<String> basePackages = new ArrayList<String>();
for (String pkg : annoAttrs.getStringArray("value")) {
if (StringUtils.hasText(pkg)) {
basePackages.add(pkg);
}
}
for (String pkg : annoAttrs.getStringArray("basePackages")) {
if (StringUtils.hasText(pkg)) {
basePackages.add(pkg);
}
}
for (Class<?> clazz : annoAttrs.getClassArray("basePackageClasses")) {
basePackages.add(ClassUtils.getPackageName(clazz));
}
//...省略代码
}
改成
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//...省略代码
List<String> basePackages = new ArrayList<String>();
for (String pkg : annoAttrs.getStringArray("value")) {
if (StringUtils.hasText(pkg)) {
basePackages.add(parsePlaceHolder(pkg));
}
}
for (String pkg : annoAttrs.getStringArray("basePackages")) {
if (StringUtils.hasText(pkg)) {
basePackages.add(parsePlaceHolder(pkg));
}
}
for (Class<?> clazz : annoAttrs.getClassArray("basePackageClasses")) {
basePackages.add(ClassUtils.getPackageName(clazz));
}
//...省略代码
}
private String parsePlaceHolder(String pro) {
if (pro != null && pro.contains(PropertySourcesPlaceholderConfigurer.DEFAULT_PLACEHOLDER_PREFIX)) {
String value = env.getProperty(pro.substring(2, pro.length() - 1));
if (logger.isDebugEnabled()) {
logger.debug("find placeholder value " + value + " for key " + pro);
}
if (null == value) {
throw new IllegalArgumentException("property " + pro + " can not find!!!");
}
return value;
}
return pro;
}
使用时,只需要使用我们自定义的MapperScanner,并且配置basePackages
@MapperScanner(basePackages = { "${db.mybatis.mapperScanner.basePackage}" }, sqlSessionFactoryRef = "sqlSessionFactory")
经过以上步骤,MapperScanner占位符功能添加成功。
使用场景分析:
- 不想在代码上写死路径,而是通过配置文件配置Mapper位置
- 在SpringApplication启动时,动态配置。结合SpringBatch可以实现只扫描当前batch下的Mapper功能
例如使用代码动态设置扫描路径
SpringApplication application = new SpringApplication(BootApplication.class);
Map<String, Object> defaultProperties = new HashMap<>();
defaultProperties.put("db.mybatis.mapperScanner.basePackage", "com.cml.springboot.batch."+batchId);
application.setDefaultProperties(defaultProperties);
application.setWebEnvironment(true);
application.run(args);
以上功能代码已提交至分支branch-mybatis-scanner