`

Mybatis IO包源码分析

阅读更多
ClassLoaderWrapper 类是对 ClassLoader 的包装. 怎么理解了?看下这个方法就知道了.

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

实例化一个 Class.
Class<?> classForName(String name, ClassLoader[] classLoader) throws ClassNotFoundException {

    for (ClassLoader cl : classLoader) {

      if (null != cl) {

        try {

          Class<?> c = Class.forName(name, true, cl);

          if (null != c) {
            return c;
          }

        } catch (ClassNotFoundException e) {
          // we'll ignore this until all classloaders fail to locate the class
        }

      }

    }

    throw new ClassNotFoundException("Cannot find class: " + name);

  }

查找资源.
URL getResourceAsURL(String resource, ClassLoader[] classLoader) {

    URL url;

    for (ClassLoader cl : classLoader) {

      if (null != cl) {

        // look for the resource as passed in...
        url = cl.getResource(resource);

        // ...but some class loaders want this leading "/", so we'll add it
        // and try again if we didn't find the resource
        if (null == url) {
          url = cl.getResource("/" + resource);
        }

        // "It's always in the last place I look for it!"
        // ... because only an idiot would keep looking for it after finding it, so stop looking already.
        if (null != url) {
          return url;
        }

      }

    }

    // didn't find it anywhere.
    return null;

  }

Resources 是 Mybatis 提供的用于读取资源文件的工具类,我们可以看到它仅仅是对 ClassLoaderWrapper 一层浅浅的封装.

VFS 是虚拟文件系统通用的 API.

VFS 提供了新增用户自定义 VFS 的功能.

看了下 VFS 的实现类,没发现啥重要的东西.

接下来的这个类比较重要. ResolverUtil.

一个测试接口,比如用于判断一个类是否是另一个类的父类,看某个类上是否存在某个注解等.
/**
   * A simple interface that specifies how to test classes to determine if they
   * are to be included in the results produced by the ResolverUtil.
   */
  public interface Test {
    /**
     * Will be called repeatedly with candidate classes. Must return True if a class
     * is to be included in the results, false otherwise.
     */
    boolean matches(Class<?> type);
  }

判断 parent 是否是 type 的父类.
public static class IsA implements Test {
    private Class<?> parent;

    /** Constructs an IsA test using the supplied Class as the parent class/interface. */
    public IsA(Class<?> parentType) {
      this.parent = parentType;
    }

    /** Returns true if type is assignable to the parent type supplied in the constructor. */
    @Override
    public boolean matches(Class<?> type) {
      return type != null && parent.isAssignableFrom(type);
    }

    @Override
    public String toString() {
      return "is assignable to " + parent.getSimpleName();
    }
  }

判断 type 上是否存在注解 annotation.
public static class AnnotatedWith implements Test {
    private Class<? extends Annotation> annotation;

    /** Constructs an AnnotatedWith test for the specified annotation type. */
    public AnnotatedWith(Class<? extends Annotation> annotation) {
      this.annotation = annotation;
    }

    /** Returns true if the type is annotated with the class provided to the constructor. */
    @Override
    public boolean matches(Class<?> type) {
      return type != null && type.isAnnotationPresent(annotation);
    }

    @Override
    public String toString() {
      return "annotated with @" + annotation.getSimpleName();
    }
  }

在 packageNames 下查找 parent 的实现类. 将查找到的结果放入 matches 集合.
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;
  }

在 packageNames 下查找被注解 annotation 修饰的类. 将查找到的结果放入 matches 集合.
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;
  }

递归查找.
public ResolverUtil<T> find(Test test, String packageName) {
    String path = getPackagePath(packageName);

    try {
      // 这里用到了 VFS,我们还是看下 VFS 的实现吧.
      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;
  }

再看下 VFS.

VFS 中定义了两个抽象方法,用于子类实现.
// 从 URL 中搜索和 forPath 匹配的路径.
protected abstract List<String> list(URL url, String forPath) throws IOException;
// 判断此 VFS 是否有效.
public abstract boolean isValid();

VFS 类定义好了获取 VFS 实例的逻辑. 优先使用用户自定义的 VFS,其次是系统实现的.
static VFS createVFS() {
      // Try the user implementations first, then the built-ins
      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++) {
        Class<? extends VFS> impl = impls.get(i);
        try {
          vfs = impl.getDeclaredConstructor().newInstance();
          if (!vfs.isValid()) {
            if (log.isDebugEnabled()) {
              log.debug("VFS implementation " + impl.getName() +
                  " is not valid in this environment.");
            }
          }
        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
          log.error("Failed to instantiate " + impl, e);
          return null;
        }
      }

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

      return vfs;
    }

关于 DefaultVFS 是读取 Jar 文件. 详细的就不分析了.
0
1
分享到:
评论

相关推荐

    Mybatis – 执行流程分析(源码分析)

    现在,需要仔细分析Mybatis的执行流程 执行流程 其实,从我们前面的工具类大致可以看出一下步骤 Resources ——》InputStream(解析xml)——》SqlSessionFactoryBuilder().build(inputStream)——》...

    zkxbatis:分析mybatis源码,实现自定义简化的mybatis复现

    源码分析 先看测试类: package uestc.zhangkx; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache....

    java8集合源码分析-Awesome-Java:真棒-Java

    集合源码分析 Java 笔记 Java 语言相关的API,第三方库和计算机基础理论等知识的学习和整理 更多 : | | 目录 资源 详细目录 Java语言和JDK源码 Java语言的基础理论知识 并发编程 Java并发编程相关的内容,并发包源码...

    java8集合源码分析-java-demos:java-演示

    集合源码分析 java-demos other collect github project leetcode springCloud [Spring Cloud 从入门到实战] () [全网最详细的一篇SpringCloud总结] () [feign] () [Spring Security 真正的前后分离实现] () [Spring...

    单点登录源码

    - 统一下单(统一下单接口、统一扫码)、订单管理、数据分析、财务报表、商户管理、渠道管理、对账系统、系统监控。 ![统一扫码支付](project-bootstrap/zheng-pay.png) &gt; zheng-ucenter 通用用户管理系统, 实现...

    最新Java面试题视频网盘,Java面试题84集、java面试专属及面试必问课程

    │ │ 13.RPC底层通讯原理之Netty线程模型源码分析.wmv │ │ │ ├─14.分库分表之后分布式下如何保证ID全局唯一性 │ │ 14.分库分表之后分布式下如何保证ID全局唯一性.mp4 │ │ │ └─15.大型公司面试必答之...

    数据库系统原理课程设计,基于 SSM 框架的医院药品库存管理系统+源代码+文档说明

    - [X] [2.6.1 导入 MyBatis 的 jar 包](#导入-MyBatis-的-jar-包) - [X] [2.6.2 配置 MyBatis](#配置-MyBatis) - [X] [2.7 配置 log4j](#配置-log4j) - [X] [2.8 集成基于 Bootstrap 前端框架的 ACE 管理...

    java版飞机大战源码-Rockira.github.io:Rockira.github.io

    java版飞机大战源码 目录(善用Ctrl+F) 注 : 没链接的是还没写 :hot_beverage: 各类知识点总结 下面的文章都有对应的原创精美PDF,在持续更新中,可以来找我催更~ Hibernate AJAX Redis ...... :hot_beverage:Java...

    积分管理系统java源码-knowledge:这是我的知识,包括我所有已知的

    积分管理系统java源码 基础知识 java基础 基本类型(占用的内存)和包装类型 数组和对象 程序控制语句,if、switch...分析Mybatis动态代理的真正实现 手动实现Mini版本的Mybatis 分布式 分布式原理 分布式架构的演进过

    GitHub 热门Java面试题

    面试题包括:基础、并发锁、JVM、设计模式、数据结构、反射/IO、面经、Spring、Spring Boot、数据库、Redis、消息队列、分布式、Zookeeper、Dubbo、Spring Cloud、Mybatis、Maven、大厂真实面经、源码分析

    基于SSM框架的在线云盘+源代码+文档说明

    1.需求分析 用户的登录注册 用户信息的更改 用户文件上传 用户文件搜索 用户下载,删除,收藏文件 2.环境准备 JDK 1.8.0_181 tomcat 8.5 spring 4.2.4 RELEASE springmvc 4.2.4 RELEASE mybatis 3.2.8 bootstrap ...

    java8源码-Java-Interview:java面试相关的一些问题

    spring、spring组件源码分析 database 数据库 动态的切换数据源,你会怎么切?读写分离? struts 数据结构 thread 多线程、并发 有关多线程的一些小例子,在《Java编程思想》中可以找到源代码 io io操作 socket 网络...

    t淘淘商城项目 商城项目 视频和源码教程 详细

    除了项目构建,Maven最核心的功能是软件包的依赖管理,能够自动分析项目所需要的依赖软件包,并到Maven中心仓库去下载。 A)管理依赖的jar包 B)管理工程之间的依赖关系。 3.2. Maven本地仓库 在当前系统用户的...

    java技术栈,包括 java基础,jvm,java集合.zip

    java技术栈,包括 java基础,jvm,java集合,java并发,IO, 设计模式,http,网络,操作系统,mysql,redis,spring,mybatis,数据结构,算法等。持续更新中,欢迎star! 各领域数据集,工具源码,适合毕业设计、...

    基于Springboot+Vue的房价可视化监测系统源码+项目说明.zip

    基于Springboot+Vue的房价可视化监测系统源码+项目说明.zip 【资源说明】 1、该资源内项目代码都是经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、...

    大数据培训课程安排.pdf

    主要技术包括:java基础语法、java⾯向对象(类、对象、封装、继承、多态、 抽象类、接⼝、常见类、内部类、常见修饰符等) 、异常、集合、⽂件、IO、 MYSQL(基本SQL语句操作、多表查询、⼦查询、存储过程、事务、...

Global site tag (gtag.js) - Google Analytics