关于java:mybatis源码分析二看源码前的思考源码入口

4次阅读

共计 3869 个字符,预计需要花费 10 分钟才能阅读完成。

一:先思考几个问题

1:BlogMapper 是个接口,接口不能实例化,如何间接调用 selectBlog 并返回

public interface BlogMapper {public Blog selectBlog(Long id);
}
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(1L);
mybatis 通过 jdk 提供动静代理解决以上问题,例如:
BlogMapper b = (BlogMapper) Proxy.
        newProxyInstance(JdkProxy.class.getClassLoader(), new Class[]{BlogMapper.class}, new InvocationHandler() {public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在调用 selectBlog 办法的时候执行 invoke
        if (method.getName().equals("selectBlog"))
            System.out.println(method.getName());
 return null; }
});
b.selectBlog(1l);

2:XML 解析

 解析 xml 的形式有多种,DOM,SAX,DOM4J,JDOM 各有优劣。mybatis 通过 SAX 解析 xml,并结构须要的对象及性能,XML 映射接口性能

二:源码入口

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory =
        new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(1L);

1:加载 xml,ClassLoaderWrapper 装璜模式加强 ClassLoader 性能

//mybatis 封装 Resources 加载 xml,实际上是调用 classLoaderWrapper.getResourceAsStream
Resources.getResourceAsStream(resource);

//ClassLoaderWrapper##getResourceAsStream
public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException {InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);
 if (in == null) {throw new IOException("Could not find resource" + resource);
 }
  return in;
}

//ClassLoaderWrapper##getResourceAsStream
public InputStream getResourceAsStream(String resource, ClassLoader classLoader) {return getResourceAsStream(resource, getClassLoaders(classLoader));
}

InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {for (ClassLoader cl : classLoader) {if (null != cl) {
        // 加载资源
        InputStream returnValue = cl.getResourceAsStream(resource);
        if (null == returnValue) {
            // 再次加载资源
            returnValue = cl.getResourceAsStream("/" + resource);
        }
        if (null != returnValue) {return returnValue;}
    }
 }
  return null;
}

//ClassLoaderWrapper 获取多级类加载器加载 xml
ClassLoader[] getClassLoaders(ClassLoader classLoader) {return new ClassLoader[]{
      // 参数指定的类加载器
      classLoader,
 // 零碎指定的默认加载器
 defaultClassLoader,
 // 以后线程的类加载器
 Thread.currentThread().getContextClassLoader(),
 // 以后类应用的类加载器
 getClass().getClassLoader(),
 //JVM 启动时就加载了类加载器
 systemClassLoader};
}

2:SqlSessionFactoryBuilder

SqlSessionFactoryBuilder 次要构建 SqlSessionFactory,SqlSessionFactory 构建 SqlSession,SqlSession 次要对数据库增删改查进行了封装 

 上图基本上是 mybatis 的壳,为对外的接口类关系
看看 build() 办法中的细节 
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
  try {
    //mybatis-config.xml 创立 XMLConfigBuilderxml 解析类
    XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
    // 返回 DefaultSqlSessionFactory##Configuration
    return build(parser.parse());
 } catch (Exception e) {throw ExceptionFactory.wrapException("Error building SqlSession.", e);
 } finally {ErrorContext.instance().reset();
 try {inputStream.close();
 } catch (IOException e) {// Intentionally ignore. Prefer previous error.}
}
}
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);

//XMLConfigBuilder 为次要解析 xml 类,其中次要调用封装的 XPathParser 解析
public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
}

private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {//new Configuration() 调用父类构造方法初始化一些值
 super(new Configuration());
 ErrorContext.instance().resource("SQL Mapper Configuration");
 this.configuration.setVariables(props);
 this.parsed = false;
 this.environment = environment;
 this.parser = parser;
}

public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) {commonConstructor(validation, variables, entityResolver);
  //createDocument 依据 xml 构建文档对象
  this.document = createDocument(new InputSource(inputStream));
}

mybatis 用建造者模式结构 Configuration 这个次要类,这个类次要蕴含数据源信息,别名缓存,mapper 映射缓存等等,从 super(new Configuration()) 开始构建 Configuration,传递给其余子类构建 Configuration 其余属性 
正文完
 0