说明
spring 的功能非常强大,如何通过 spring 扫描指定包呢?
比如我们想获取指定包下的所有枚举。
实现
package com.github.houbb.spring.tool.utils;
import com.github.houbb.heaven.util.lang.StringUtil;
import com.github.houbb.spring.tool.exception.SpringToolException;
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.ClassUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* spring 包工具类
*
* @since 1.0.0
*/
public class SpringPackageUtil {
/**
* 扫描
* @param basePackages 基础包信息
* @param resourcePattern 资源正则
*/
public static List<String> scanClassName(String basePackages, String resourcePattern) {
try {
List<String> classNameList = new ArrayList<>();
if(StringUtil.isEmpty(basePackages)
|| StringUtil.isEmpty(resourcePattern)) {
return classNameList;
}
final ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
// 根据classname生成class对应的资源路径,需要扫描的包路径
//ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
String pattern = ClassUtils.convertClassNameToResourcePath(basePackages) + resourcePattern;
// 获取classname的IO流资源
Resource[] resources = resourcePatternResolver.getResources(pattern);
// MetadataReaderFactory接口 ,MetadataReader的工厂接口。允许缓存每个MetadataReader的元数据集
MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
for (Resource resource : resources) {
if (resource.isReadable()) {
// 通过class资源(resource)生成MetadataReader
MetadataReader metadataReader = readerFactory.getMetadataReader(resource);
// 获取class名
String className = metadataReader.getClassMetadata().getClassName();
classNameList.add(className);
}
}
return classNameList;
} catch (Exception e) {
throw new SpringToolException(e);
}
}
/**
* 扫描
* @param basePackages 基础包信息
* @param resourcePattern 资源正则
*/
public static List<Class> scanClass(String basePackages, String resourcePattern) {
List<String> nameList = scanClassName(basePackages, resourcePattern);
return nameList.stream().map((Function<String, Class>) s -> {
try {
return Class.forName(s);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}).collect(Collectors.toList());
}
}
测试
测试路径
PS D:\code\learn\spring-tool\src\test>
└─com
└─github
└─houbb
└─spring
└─tool
│ package-info.java
│
├─enums
│ MyBoolEnum.java
│ package-info.java
│
└─utils
SpringPackageUtilTest.java
使用
List<String> nameList = SpringPackageUtil.scanClassName("com.github.houbb.spring.tool.enums", "/**/*Enum.class");
System.out.println(nameList);
直接扫描包下面对应的 Enum 类信息。
[com.github.houbb.spring.tool.enums.MyBoolEnum]
参考资料
https://github.com/dianping/cat/blob/master/lib/java/README.zh-CN.md
https://github.com/dianping/cat/blob/master/integration/log4j2/README.md