包括了这几个类:
ClassLoaderWrapper DefaultVFS ExternalResources JBoss6VFS ResolverUtil Resources VFS
ClassLoaderWrapper 类 使用5种类加载器,one by one查找资源,只要其中一个命中,就OK
尽最大可能找到指定的资源
Resources 类 简化资源文件的获取。 主要是通过ClassLoaderWrapper(封装ClassLoader读取文件)进行文件加载
ClassLoaderWrapper ,为啥又定义 Resources 类 ClassLoderWrapper 作为 Resouces 类的一个成员变量,将前者提供的方法都包装成静态方法,方便调用。 并且扩展了其他资源读取的方法,eg: getResourceAsProperties() 。看着有点像是装饰模式的样子~~
ResolverUtil 类 ResolverUtil用于查找在类路径可用并满足任意条件的类。最常见的两种情况是一个类继承或实现了另一个类, 或者此类被指定的注解标记了。并且,通过使用Test类,可以满足任意条件的搜索。即找一个package下满足条件的所有类
/**
* 主要的方法,找一个package下满足条件的所有类,被TypeHandlerRegistry, MapperRegistry, TypeAliasRegistry调用
* 1. 浏览提供的包及其子包的类
* 2. 每个发现的类都会被提供给Test类,如果Test类的方法返回true就保留
* 3. 累的类可以通过getClasses()方法获得
*/
public ResolverUtil<T> find(Test test, String packageName) {
String path = getPackagePath(packageName);
try {
// 通过VFS来深入jar包里面去找一个class
List<String> children = VFS.getInstance().list(path);
for (String child : children) {
if (child.endsWith(".class")) {
addIfMatching(test, child);
}
}
} catch (IOException ioe) {
log.error("Could not read package: " + packageName, ioe);
}
return this;
}
复制代码
在当前包中查找所有被 CacheNamespace 注解修饰的类
@Test
void findAnnotated() {
ResolverUtil<Object> resolverUtil = new ResolverUtil<>();
// 在当前包中查找所有被CacheNamespace注解修饰的类
resolverUtil.findAnnotated(CacheNamespace.class, this.getClass().getPackage().getName());
Set<Class<?>> classSets = resolverUtil.getClasses();
//org.apache.ibatis.io.ResolverUtilTest.TestMapper
assertEquals(classSets.size(), 1);
classSets.forEach(c -> assertNotNull(c.getAnnotation(CacheNamespace.class)));
}
复制代码
很巧妙的应用了 设计模式原则的开发-封闭原则 。在这个工具类中,定义了一个内部接口Test和两个Test的内部实现类。 使得我们可以只实现Test接口,而不用修改 ResolverUtil 的内部方法,即可直接使用 ResolverUtil 的 find 方法
public class CustomTest implements Test {
@Override
public boolean matches(Class<?> type) {
if (type == CustomTest.class) {
return true;
}
return false;
}
}
复制代码