mybatis 源码系列 组件之 io

Question:

. io包 提供了 哪些 工具类?

. 工具类的实现? 


1. ClassLoaderWrapper

提供 根据 Resource 来 获取 相应的 URL , InputStream, 

提供 根据 class 名称 获取 相应的 class

其最为重要的方法无非是对 各种 classloader进行了一个包装,如下:

ClassLoader[] getClassLoaders(ClassLoader classLoader) {
    return new ClassLoader[]{
        classLoader, 
        defaultClassLoader, 
        Thread.currentThread().getContextClassLoader(), 
        getClass().getClassLoader(), 
        systemClassLoader}; 
  }


这样,在 相应的 方法里,包括 getResourceAsURL , classForName, getResourceAsStream, 都是对 这个 classLoader 数组进行遍历, 如果 遍历下的 classloader 不为空,则用这个 classloader 来加载 相应的 url, class, inputstream


2. Resources

对 ClassLoaderWrapper 进行了包装, 提供给外部接口调用


3. VFS

Provides a very simple API for accessing resources within an application server.提供简单的api 从相应服务器获取resource, 其实现类包括DefaultVFS 和 JBoss6VFS,提供的api为:

/**
   * Recursively list the full resource path of all the resources that are children of all the
   * resources found at the specified path.
   * 
   * @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<String>();
    for (URL url : getResources(path)) {
      names.addAll(list(url,path));
    }
    return names;
  }


即 获取某一路劲下及其子节点下的 Resouce,同时, 其用了单例模式来提供实例给外部接口调用:

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

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

  /** Singleton instance. */
  private static VFSinstance;

  /**
   * Get the singleton {@link VFS} instance. If no{@link VFS} implementation can be found for the
   * current environment, then this method returns null.
   */
  @SuppressWarnings("unchecked")
  public static VFS getInstance() {
    if (instance !=null)
      return instance;

    // Try the user implementations first, then the built-ins
    List<Class<? extends VFS>> impls = new ArrayList<Class<? extends VFS>>();
    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++) {
      Class<? extends VFS> impl = impls.get(i);
      try {
        vfs = impl.newInstance();
        if (vfs == null || !vfs.isValid()) {
          log.debug("VFS implementation " +impl.getName() +
              " is not valid in this environment.");
        }
      } catch (InstantiationException e) {
        log.error("Failed to instantiate " +impl,e);
        return null;
      } catch (IllegalAccessException e) {
        log.error("Failed to instantiate " +impl,e);
        return null;
      }
    }

    log.debug("Using VFS adapter " +vfs.getClass().getName());
    return VFS.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);
  }



可以看到,外部类 可以 自己 编写 相应的 VFS实现类,并调用 addImplClass 将 自己实现类 加入到USER_IMPLEMENTATIONS list中,并在getInstance 方法中,能够保证 自己实现的类 被先用到,当然,如果没有自己实现,mybatis会用默认的JBoss6VFS.class, DefaultVFS.class中的一个,当然,如果想了解 DefautlVFS 和JBoss6VFS 的可以花时间看看,看其是怎么 从 jar包中读取Resouce的,要注意哪些事情,当然,以后如果用到,也可以想到 mybatis已经实现了,可以覆用!


4. ExternalResources

. 利用 jdk1.7新特性 closeable 接口 关闭FileChannel, 同时 利用 nio的FileChannel实现 了 文件的拷贝,将 文件 内容从souceFile 拷贝到 destFile

. getConfiguredTemplate(StringtemplatePath, StringtemplateProperty) 从 某一份Properties 文件中获取 某一个 属性的值


5. ResolverUtil

在提供的包名或者其子节点下的路劲下寻找符合一定条件的 class, 包括 是否 实现 或者 继承 某一个类, 或者 这个类是否被某一个 annotation 标识了,其中最重要的 无非是:

.  parent.isAssignableFrom(type); // 可以 对比 instanceof , 了解其区别

. type.isAnnotationPresent(annotation); // 判断 type 是否被annotation 注解了


提供的接口如下:

/**
   * Attempts to discover classes that are assignable to the type provided. In the case
   * that an interface is provided this method will collect implementations. In the case
   * of a non-interface class, subclasses will be collected.  Accumulated classes can be
   * accessed by calling {@link #getClasses()}.
   *
   * @param parent the class of interface to find subclasses or implementations of
   * @param packageNames one or more package names to scan (includingsubpackages) for classes
   */
  public ResolverUtil<T> findImplementations(Class<?>parent, String...packageNames) {
    if (packageNames ==null)
      return this;

    Test test = new IsA(parent);
    for (String pkg :packageNames) {
      find(test, pkg);
    }

    return this;
  }

  /**
   * Attempts to discover classes that are annotated with the annotation. Accumulated
   * classes can be accessed by calling {@link #getClasses()}.
   *
   * @param annotation the annotation that should be present on matching classes
   * @param packageNames one or more package names to scan (includingsubpackages) for classes
   */
  public ResolverUtil<T> findAnnotated(Class<?extends Annotation>annotation, String...packageNames) {
    if (packageNames ==null)
      return this;

    Test test = new AnnotatedWith(annotation);
    for (String pkg :packageNames) {
      find(test, pkg);
    }

    return this;
  }

  /**
   * Scans for classes starting at the package provided and descending intosubpackages.
   * Each class is offered up to the Test as it is discovered, and if the Test returns
   * true the class is retained.  Accumulated classes can be fetched by calling
   * {@link #getClasses()}.
   *
   * @param test an instance of {@link Test} that will be used to filter classes
   * @param packageName the name of the package from which to start scanning for
   *        classes, e.g. {@code net.sourceforge.stripes}
   */
  public ResolverUtil<T> find(Test test, String packageName) {
    String path = getPackagePath(packageName);

    try {
      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;
  }




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值