获取包路径下的资源
- 场景介绍
在一个需求里,我需要获取某个包路径下的所有类的方法,例如:我要获取com.it.hsrcm.pbs.api
包路径下的所有方法名 (同理可以获取所有的类名等…)
不得不说需求真的是奇奇怪怪,不怕遇不到,就怕百度的时候遇上那些神一样的文章,问题解决不了,叽里呱啦说了大半页,到了关键时刻公布真相的时候,他不行了,开始让你点赞了 - 获取方式介绍
通过实现SpringBoot
的接口ResourceLoaderAware
获取
一、包路径介绍
1.1 classpath: 的真实含义
classpath:
指的是class
路径前缀
在org.springframework.util.ResourceUtils.ResourceLoader
中介绍了classpath:
的作用,它和WEB-INF/
的区别很大
classpath:
和classpath*:
的区别
在org.springframework.core.io.support.ResourcePatternResolver
中说的很明白,大哥们的话简洁明了,只为少写一些注释,也让那些说不清区别的人别再出来祸祸其他的幼崽
用classpath:
只能找到一个,你必须还要写上这个文件的路径,但是用classpath*:
,你能拿到一切Resource
路径的种类
我们常说的Resource
指的是我们可以通过API
加载到的任何一个资源,那么我们该如何通过路径去加载一个resource
呢,在该类下面也给出了几种方式
① 通过绝对路径加载一个Resource
例:file:C:/test.dat
② 通过类的伪路径加载一个Resource
例:classpath:test.dat
③ 通过Resource
的相对路径加载 例:WEB-INF/test.dat
二、ResourceLoaderAware
2.1 实现ResourceLoaderAware接口
/**
* 资源扫描
*
* <p>扫描指定的包路径{@link #CLASS_SCAN_PACKAGE_PATH},获取包路劲想爱的所有
* {@link java.lang.Class}
*/
static class ScanSupport implements ResourceLoaderAware {
private ResourceLoader resourceLoader = new PathMatchingResourcePatternResolver();
private final ResourcePatternResolver resolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
private final MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
private static final String CLASS_SCAN_PACKAGE_PATH = "com.hundsun.hsrcm.pbs.api.rpc.service";
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
/**
* 扫描公共接口包,获取所有的公共接口并加入白名单
*
* @return
* @throws IOException
*/
public Set<Class<?>> doScan() throws IOException {
Set<Class<?>> classes = new HashSet<>();
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
.concat(ClassUtils.convertClassNameToResourcePath(SystemPropertyUtils.resolvePlaceholders(CLASS_SCAN_PACKAGE_PATH))
.concat("/**/*.class"));
Resource[] resources = resolver.getResources(packageSearchPath);
MetadataReader metadataReader = null;
for (Resource resource : resources) {
if (resource.isReadable()) {
metadataReader = metadataReaderFactory.getMetadataReader(resource);
try {
classes.add(Class.forName(metadataReader.getClassMetadata().getClassName()));
} catch (Exception e) {
log.info("公共接口信息解析错误:{}", e.getMessage());
}
}
}
return classes;
}
}
2.2 源码分析
① 在 org.springframework.core.io
下提供了 ResourceLoader
接口
② org.springframework.core.io.support
下的 ResourcePatternResolver
继承了上述接口
public interface ResourcePatternResolver extends ResourceLoader {
String CLASSPATH_ALL_URL_PREFIX = "classpath*:";
Resource[] getResources(String locationPattern) throws IOException;
}
③ 主要的方法为 PathMatchingResourcePatternResolver
该类下的 getResources(String locationParttern)
④ 这种方法主要去获取 locationParttern
为前面三种路径下的匹配项