一:先思考几个问题
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.getResourceAsStreamResources.getResourceAsStream(resource);//ClassLoaderWrapper##getResourceAsStreampublic 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##getResourceAsStreampublic 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获取多级类加载器加载xmlClassLoader[] 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其余属性