包括了这几个类:
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; } } 复制代码