Mybatis源码-VFS(虚拟文件系统)

VFS 是虚拟文件系统通用API,不需关心不一样服务的存储媒介什么,高层的抽象,这个在mybatis是一个抽象类,它有两个实现类一个是默认,一个是JBoss的java

一、继承图示

在这里插入图片描述

1.1. 子类须要实现只有两个方法:
  1. isValid()是否有效
  2. list(URL url, String forPath) 列出某个path对应URL的全部子资源,递归获取

二、VFS源码(注释)

/** * Provides a very simple API for accessing resources within an application server. * 1. VFS是虚拟文件系统通用API,不需关心什么存储媒介 * 2. 优先使用自定义实现VFS,最后使用mybatis内置的JBoss6VFS和DefaultVFS * 3. 利用静态内部类VFSHolder实现单例,根据顺序自定义实现VFS> 内置原则,实例VFS * @author Ben Gunter */
public abstract class VFS {
  private static final Log log = LogFactory.getLog(VFS.class);

  /** The built-in implementations. */
  /** * 内置实现JBoss6VFS和DefaultVFS */
  public static final Class<?>[] IMPLEMENTATIONS = { JBoss6VFS.class, DefaultVFS.class };

  /** * 用户实现的VFS的类 */
  /** The list to which implementations are added by {@link #addImplClass(Class)}. */
  public static final List<Class<? extends VFS>> USER_IMPLEMENTATIONS = new ArrayList<>();

  /** * 建立一个单例VFS容器 */
  /** Singleton instance holder. */
  private static class VFSHolder {
    /** * 建立一个单例对象 */
    static final VFS INSTANCE = createVFS();

    @SuppressWarnings("unchecked")
    static VFS createVFS() {
      // Try the user implementations first, then the built-ins
      // 先加入用户自定义的
      // 加载mybatis内置实现的
      List<Class<? extends VFS>> impls = new ArrayList<>();
      impls.addAll(USER_IMPLEMENTATIONS);
      impls.addAll(Arrays.asList((Class<? extends VFS>[]) IMPLEMENTATIONS));

      // Try each implementation class until a valid one is found
      VFS vfs = null;
      for (int i = 0; vfs == null || !vfs.isValid(); i++) {
        // 循环遍历,直到找到有效VFS实现类
        // 获取VFS实现类
        Class<? extends VFS> impl = impls.get(i);
        try {
          // 实例化一个对象
          vfs = impl.newInstance();
          if (vfs == null || !vfs.isValid()) {
            if (log.isDebugEnabled()) {
              log.debug("VFS implementation " + impl.getName() +
                  " is not valid in this environment.");
            }
          }
        } catch (InstantiationException | IllegalAccessException e) {
          log.error("Failed to instantiate " + impl, e);
          return null;
        }
      }

      if (log.isDebugEnabled()) {
        log.debug("Using VFS adapter " + vfs.getClass().getName());
      }

      return vfs;
    }
  }

  /** * 返回一个VFS实现的单例实例 * Get the singleton {@link VFS} instance. If no {@link VFS} implementation can be found for the * current environment, then this method returns null. */
  public static VFS getInstance() {
    return VFSHolder.INSTANCE;
  }

  /** * 添加用户自定义的VFS实现类 * Adds the specified class to the list of {@link VFS} implementations. Classes added in this * manner are tried in the order they are added and before any of the built-in implementations. * * @param clazz The {@link VFS} implementation class to add. */
  public static void addImplClass(Class<? extends VFS> clazz) {
    if (clazz != null) {
      USER_IMPLEMENTATIONS.add(clazz);
    }
  }

  /** * 获取类Class,直接经过当前线程获取 */
  /** Get a class by name. If the class is not found then return null. */
  protected static Class<?> getClass(String className) {
    try {
      return Thread.currentThread().getContextClassLoader().loadClass(className);
// return ReflectUtil.findClass(className);
    } catch (ClassNotFoundException e) {
      if (log.isDebugEnabled()) {
        log.debug("Class not found: " + className);
      }
      return null;
    }
  }

  /** * Get a method by name and parameter types. If the method is not found then return null. * 经过类,方法名,方法参数类型获取对应方法 * @param clazz The class to which the method belongs. * @param methodName The name of the method. * @param parameterTypes The types of the parameters accepted by the method. */
  protected static Method getMethod(Class<?> clazz, String methodName, Class<?>... parameterTypes) {
    if (clazz == null) {
      return null;
    }
    try {
      return clazz.getMethod(methodName, parameterTypes);
    } catch (SecurityException e) {
      log.error("Security exception looking for method " + clazz.getName() + "." + methodName + ". Cause: " + e);
      return null;
    } catch (NoSuchMethodException e) {
      log.error("Method not found " + clazz.getName() + "." + methodName + "." + methodName + ". Cause: " + e);
      return null;
    }
  }

  /** * Invoke a method on an object and return whatever it returns. * 方法调用 * @param method The method to invoke. 该方法将会被调用 * @param object The instance or class (for static methods) on which to invoke the method. 一个实例或静态方法 * @param parameters The parameters to pass to the method. 方法入参 * @return Whatever the method returns. * @throws IOException If I/O errors occur * @throws RuntimeException If anything else goes wrong */
  @SuppressWarnings("unchecked")
  protected static <T> T invoke(Method method, Object object, Object... parameters)
      throws IOException, RuntimeException {
    try {
      return (T) method.invoke(object, parameters);
    } catch (IllegalArgumentException | IllegalAccessException e) {
      throw new RuntimeException(e);
    } catch (InvocationTargetException e) {
      if (e.getTargetException() instanceof IOException) {
        throw (IOException) e.getTargetException();
      } else {
        throw new RuntimeException(e);
      }
    }
  }

  /** * Get a list of {@link URL}s from the context classloader for all the resources found at the * specified path. * 在特定路径下加载全部资源URL返回 * @param path The resource path. * @return A list of {@link URL}s, as returned by {@link ClassLoader#getResources(String)}. * @throws IOException If I/O errors occur */
  protected static List<URL> getResources(String path) throws IOException {
    // 将枚举类转成集合
    return Collections.list(Thread.currentThread().getContextClassLoader().getResources(path));
  }

  /** * 判断是否有效 */
  /** Return true if the {@link VFS} implementation is valid for the current environment. */
  public abstract boolean isValid();

  /** * Recursively list the full resource path of all the resources that are children of the * resource identified by a URL. * 递归列出URL的下全部子的资源列表 * @param url The URL that identifies the resource to list. * @param forPath The path to the resource that is identified by the URL. Generally, this is the * value passed to {@link #getResources(String)} to get the resource URL. * @return A list containing the names of the child resources. * @throws IOException If I/O errors occur */
  protected abstract List<String> list(URL url, String forPath) throws IOException;

  /** * Recursively list the full resource path of all the resources that are children of all the * resources found at the specified path. * 列出某个路径全部URL对应子资源 * @param path The path of the resource(s) to list. * @return A list containing the names of the child resources. * @throws IOException If I/O errors occur */
  public List<String> list(String path) throws IOException {
    List<String> names = new ArrayList<>();
    for (URL url : getResources(path)) {
      names.addAll(list(url, path));
    }
    return names;
  }
}
2.一、总结
  1. VFS是虚拟文件系统通用API,不需关心什么存储媒介
  2. 优先使用自定义实现VFS,最后使用mybatis内置的JBoss6VFS和DefaultVFS
  3. 利用静态内部类VFSHolder实现单例,根据顺序自定义实现VFS> 内置原则,实例VFS