前言
最近项目组接到了一个新的需求,因为部署限制,需要把mybatis的xml文件放到jar包之外。项目的技术栈用的springboot,之前就是打一个jar包就完事,没有做过类似的需求。因此,我想着是从源码入手,解决这个问题。
动手
因为项目是基于springboot,就从springboot整合mybatis看。按照springboot的套路,找到了MybatisAutoConfiguration。
if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
factory.setMapperLocations(this.properties.resolveMapperLocations());
}
properties 为MybatisProperties,继续看properties.resolveMapperLocations()
public Resource[] resolveMapperLocations() {
return Stream.of(Optional.ofNullable(this.mapperLocations).orElse(new String[0]))
.flatMap(location -> Stream.of(getResources(location))).toArray(Resource[]::new);
}
private Resource[] getResources(String location) {
try {
return resourceResolver.getResources(location);
} catch (IOException e) {
return new Resource[0];
}
}
通过以上代码分析,就是把xml文件转换成Resource,那么我们可以修改这个方法,把我们的xml文件加到这个数据里面。那么springaop的环绕通知就适合这种场景。我们定义一个切面,对properties.resolveMapperLocations()进行增强即可。
@Aspect
@Component
public class MybatisPropertiesAop {
@Value("${outer.mapper}")
public String outerLocation;
@Around("execution(* org.mybatis.spring.boot.autoconfigure.MybatisProperties.resolveMapperLocations(..))")
public Object addXml(ProceedingJoinPoint joinPoint) throws Throwable {
Resource[] proceed =(Resource[]) joinPoint.proceed();
Resource[] resourceFromOuter = getResourceFromOuter(outerLocation);
Resource[] merge=new Resource[proceed.length+resourceFromOuter.length];
System.arraycopy(proceed, 0, merge, 0, proceed.length);
System.arraycopy(resourceFromOuter, 0, merge, proceed.length, resourceFromOuter.length);
return merge;
}
private Resource[] getResourceFromOuter(String outerLocation) {
File file=new File(outerLocation);
File[] files = file.listFiles();
List<Resource> resourceList=new ArrayList<>();
for (File f:files){
if(f.getName().endsWith("xml")){
resourceList.add(new FileSystemResource(f));
}
}
return resourceList.toArray(new Resource[resourceList.size()]);
}
}
以上代码就是一个例子,经过测试可行。
让我们保持一颗虔诚的心,在伟人的肩膀上继续攀登。