模块总览
ClassLoaderWrapper
:ClassLoader的包装类。DefaultVFS
:VFS的默认实现类。ExternalResources
:已经废弃了。JBoss6VFS
:JBoss 6实现的VFS。ResolverUtil
:用来通过某种方式来查找类,如果满足某个条件就查出该类。Resources
:通过类加载器简单的访问资源。VFS
:是提供用于访问应用内资源的一个简便接口。
ClassLoaderWrapper
类
作用
使用5种类加载器,one by one查找资源,只要其中一个命中,就OK
- 自定义类加载器 > 默认类加载器 > 当前线程Id上下文类加载器 > 当前类的加载器 > 系统类加载器
- 封装加载类资源有三种,一种返回URL、一种是返回InputStream,最后一种根据类名返回Class
- 在实例化该对象的时候默认会赋值系统类加载器
类图
Thinking
- 为什么需要用5种不同的类加载器
尽最大可能找到指定的资源
- 每种类加载器的异同
Resources
类
作用
简化资源文件的获取。 主要是通过ClassLoaderWrapper(封装ClassLoader读取文件)进行文件加载
- 对于简单的只读文本数据,加载为 Reader
- 对于简单的只读二进制或文本数据,加载为 InputStream
- 对于可读写的二进制或文本文件,加载为 File
- 对于只读的配置属性文件,加载为 Properties
- 对于只读的通用资源,加载为 URL
类图
Thinking
- 有了
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;
}
复制代码
UT
在当前包中查找所有被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)));
}
复制代码
Thinking
很巧妙的应用了设计模式原则的开发-封闭原则。在这个工具类中,定义了一个内部接口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;
}
}
复制代码