org.zodiac.autoconfigure.mybatisplus.MyBatisPlusSqlSessionFactoryCustomizer Maven / Gradle / Ivy
package org.zodiac.autoconfigure.mybatisplus;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.zodiac.commons.util.Colls;
import org.zodiac.commons.util.lang.Strings;
import org.zodiac.mybatis.exception.MyBatisException;
import org.zodiac.mybatis.handler.SmartEnumTypeHandler;
import org.zodiac.sdk.toolkit.constants.StringPool;
public class MyBatisPlusSqlSessionFactoryCustomizer {
private String typeEnumsPackage;
private SqlSessionFactory sqlSessionFactory;
private ApplicationContext applicationContext;
public MyBatisPlusSqlSessionFactoryCustomizer(String enumsPackage, SqlSessionFactory sqlSessionFactory,
ApplicationContext applicationContext) {
this.typeEnumsPackage = enumsPackage;
this.sqlSessionFactory = sqlSessionFactory;
this.applicationContext = applicationContext;
List basePackage = Colls.list();
if (Strings.isNotEmpty(this.typeEnumsPackage)) {
basePackage.addAll(Arrays.asList(this.typeEnumsPackage.split(",")));
} else {
/*从注解中解析basePackage*/
Map applicationClass =
this.applicationContext.getBeansWithAnnotation(SpringBootApplication.class);
applicationClass.forEach((k, v) -> {
SpringBootApplication ann = AnnotationUtils.findAnnotation(v.getClass(), SpringBootApplication.class);
if (ann.scanBasePackages().length == 0 && ann.scanBasePackageClasses().length == 0) {
basePackage.add(v.getClass().getPackage().getName());
} else {
basePackage.addAll(Arrays.asList(ann.scanBasePackages()));
basePackage.addAll(Arrays.asList(ann.scanBasePackageClasses()).stream()
.map(s -> s.getPackage().getName()).collect(Collectors.toList()));
}
});
List newPackage =
basePackage.stream().map(s -> s.endsWith("*") ? s : s + ".**").collect(Collectors.toList());
basePackage.clear();
basePackage.addAll(newPackage);
}
this.typeEnumsPackage = basePackage.stream().collect(Collectors.joining(","));
if (Strings.notBlank(this.typeEnumsPackage)) {
// Set classes;
// if (null != typeEnumsPackage && typeEnumsPackage.contains(StringPool.STAR) && !typeEnumsPackage.contains(StringPool.COMMA)
// && !typeEnumsPackage.contains(StringPool.SEMICOLON)) {
// classes = PackageHelper.scanTypePackage(typeEnumsPackage);
// } else {
// String[] typeEnumsPackageArray = StringUtils.tokenizeToStringArray(this.typeEnumsPackage,
// ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
// Assert.notNull(typeEnumsPackageArray, String.format("Not find typeEnumsPackage: %s .", this.typeEnumsPackage));
// classes = new HashSet<>();
// for (String typePackage : typeEnumsPackageArray) {
// Set scanTypePackage = PackageHelper.scanTypePackage(typePackage);
// if (scanTypePackage.isEmpty()) {
// } else {
// classes.addAll(PackageHelper.scanTypePackage(typePackage));
// }
// }
// }
// /*取得类型转换注册器*/
// TypeHandlerRegistry typeHandlerRegistry = this.sqlSessionFactory.getConfiguration().getTypeHandlerRegistry();
// for (Class cls : classes) {
// if (cls.isEnum()) {
// /*原生方式*/
// registerOriginalEnumTypeHandler(typeHandlerRegistry, cls);
// }
// }
Set classes;
if (this.typeEnumsPackage.contains(StringPool.STAR) && !this.typeEnumsPackage.contains(StringPool.COMMA)
&& !this.typeEnumsPackage.contains(StringPool.SEMICOLON)) {
classes = PackageHelper.scanTypePackage(this.typeEnumsPackage);
} else {
String[] typeEnumsPackageArray = StringUtils.tokenizeToStringArray(this.typeEnumsPackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
Assert.notNull(typeEnumsPackageArray, String.format("Not find typeEnumsPackage: %s .", this.typeEnumsPackage));
classes = Colls.set();
for (String typePackage : typeEnumsPackageArray) {
Set scanTypePackage = PackageHelper.scanTypePackage(typePackage);
if (scanTypePackage.isEmpty()) {
} else {
classes.addAll(PackageHelper.scanTypePackage(typePackage));
}
}
}
/*取得类型转换注册器*/
TypeHandlerRegistry typeHandlerRegistry = this.sqlSessionFactory.getConfiguration().getTypeHandlerRegistry();
for (Class cls : classes) {
if (cls.isEnum()) {
/*原生方式*/
registerOriginalEnumTypeHandler(typeHandlerRegistry, cls);
}
}
}
}
protected void registerOriginalEnumTypeHandler(TypeHandlerRegistry typeHandlerRegistry, Class> enumClazz) {
typeHandlerRegistry.register(enumClazz, SmartEnumTypeHandler.class);
}
static class PackageHelper {
/**
* 别名通配符设置。
*
* >property name="typeAliasesPackage" value="com.baomidou.*.entity"/>
*
*
* @param typeAliasesPackage 类别名包路径
* @return 包名称列表
*/
public static String[] convertTypeAliasesPackage(String typeAliasesPackage) {
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
String pkg = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
+ ClassUtils.convertClassNameToResourcePath(typeAliasesPackage) + "/*.class";
/*
* 将加载多个绝对匹配的所有Resource
* 将首先通过ClassLoader.getResource("META-INF")加载非模式路径部分,然后进行遍历模式匹配,排除重复包路径
*/
try {
Set set = Colls.set();
Resource[] resources = resolver.getResources(pkg);
if (resources != null && resources.length > 0) {
MetadataReader metadataReader;
for (Resource resource : resources) {
if (resource.isReadable()) {
metadataReader = metadataReaderFactory.getMetadataReader(resource);
set.add(
Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName());
}
}
}
if (!set.isEmpty()) {
return set.toArray(new String[] {});
}
return new String[0];
} catch (Exception e) {
throw new MyBatisException(String.format("Not find typeAliasesPackage: %s", pkg), e);
}
}
/**
* 扫描获取指定包路径所有类。
*
* @param typePackage 扫描类包路径,多个用{@code ,}分割
* @return 类集合
*/
public static Set scanTypePackage(String typePackage) {
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
String pkg = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
+ ClassUtils.convertClassNameToResourcePath(typePackage) + "/*.class";
/*
* 将加载多个绝对匹配的所有Resource
* 将首先通过ClassLoader.getResource("META-INF")加载非模式路径部分,然后进行遍历模式匹配,排除重复包路径
*/
try {
Set set = Colls.set();
Resource[] resources = resolver.getResources(pkg);
if (resources != null && resources.length > 0) {
MetadataReader metadataReader;
for (Resource resource : resources) {
if (resource.isReadable()) {
metadataReader = metadataReaderFactory.getMetadataReader(resource);
set.add(Class.forName(metadataReader.getClassMetadata().getClassName()));
}
}
}
return set;
} catch (Exception e) {
throw new MyBatisException(String.format("Not find scanTypePackage: %s", pkg), e);
}
}
/**
* 新建文件目录。
*
* @param file 文件
*/
public static void mkDir(File file) {
if (file.getParentFile().exists()) {
file.mkdir();
} else {
mkDir(file.getParentFile());
file.mkdir();
}
}
}
}