程序员人生 网站导航

mybatis源码总结--快速入门

栏目:互联网时间:2014-12-23 08:24:49

首先在此声明,本人是通过学习湖畔微风《深入浅出mybatis》基础之上对代码进行总结。

《深入浅出mybatis》 http://blog.csdn.net/hupanfeng/article/details/9068003

 1、mybatis解析配置文件

SqlSessionFactoryBuilder类是mybatis的入口,在创建SqlSeesionFactory时会解析配置文件,将文件中的信息保存在Configuration对象中。

其中的类XmlConfigureBulider类其中,调用XPathParser类的parse方法,获得configuration根节点并调用parseConfiguration方法,XPathParser为解析xml的核心类

public Configuration parse() { if (parsed) { throw new BuilderException("Each XMLConfigBuilder can only be used once."); } parsed = true; parseConfiguration(parser.evalNode("/configuration")); return configuration; }
parseConfiguration方法相当于1个中转站,它获得configuration下不同的子节点,并调用相应的方法去解析

private void parseConfiguration(XNode root) { try { propertiesElement(root.evalNode("properties")); //issue #117 read properties first typeAliasesElement(root.evalNode("typeAliases")); pluginElement(root.evalNode("plugins")); objectFactoryElement(root.evalNode("objectFactory")); objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); settingsElement(root.evalNode("settings")); environmentsElement(root.evalNode("environments")); // read it after objectFactory and objectWrapperFactory issue #631 databaseIdProviderElement(root.evalNode("databaseIdProvider")); typeHandlerElement(root.evalNode("typeHandlers")); mapperElement(root.evalNode("mappers")); } catch (Exception e) { throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); } }
上述两个方法中都用到了evalNode方法返回Xnode类,其中evaluate方法获得目标结节点,并创建XNode 类

public XNode evalNode(Object root, String expression) { Node node = (Node) evaluate(expression, root, XPathConstants.NODE); if (node == null) { return null; } return new XNode(this, node, variables); }
Xnode中的构造方法,解析了节点属性和所有子节点
构造方法:
</pre><pre name="code" class="java"> public XNode(XPathParser xpathParser, Node node, Properties variables) { this.xpathParser = xpathParser; this.node = node; this.name = node.getNodeName(); this.variables = variables; this.attributes = parseAttributes(node); this.body = parseBody(node); }

解析属性:

private Properties parseAttributes(Node n) { Properties attributes = new Properties(); NamedNodeMap attributeNodes = n.getAttributes(); if (attributeNodes != null) { for (int i = 0; i < attributeNodes.getLength(); i++) { Node attribute = attributeNodes.item(i); String value = PropertyParser.parse(attribute.getNodeValue(), variables); attributes.put(attribute.getNodeName(), value); } } return attributes; }
获得所有子节点:

private String parseBody(Node node) { String data = getBodyData(node); if (data == null) { NodeList children = node.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); data = getBodyData(child); if (data != null) break; } } return data; }

总结:(1)通过学习源代码了解解析流程

            (2)学习1下解析XML程序设计的思路。mybatis设计解析xml符合开闭原则,如果以后配置文件要在configuration节点下增加新的子节点,只需增加相应的解析方法,其它地方基本不用修改。如果已存在的子节点中内容有修改,只需修改不同子节点相应的方法,不会对其它解析节点方法产生影响。

2、SqlSession对数据库的操作

在《mybatis深入浅出》中所说SqlSession对数据库的操作以下:

SqlSession session= sqlSessionFactory.openSession(); UserDao userDao = session.getMapper(UserDao.class); UserDto user = new UserDto(); user.setUsername("iMybatis"); List<UserDto> users = userDao.queryUsers(user);
其中session.getMapper(UserDao.class)获得的是UserDao的代理对象

先获得创建代理对象的工厂类

public <T> T getMapper(Class<T> type, SqlSession sqlSession) { final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type); if (mapperProxyFactory == null) throw new BindingException("Type " + type + " is not known to the MapperRegistry."); try { return mapperProxyFactory.newInstance(sqlSession); } catch (Exception e) { throw new BindingException("Error getting mapper instance. Cause: " + e, e); } }
在工厂类中,创建代理对象

protected T newInstance(MapperProxy<T> mapperProxy) { return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy); } public T newInstance(SqlSession sqlSession) { final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache); return newInstance(mapperProxy); }
代理类中,履行完目标方法后,会将method存入cacheMapperMethod供以后调用。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (Object.class.equals(method.getDeclaringClass())) { return method.invoke(this, args); } final MapperMethod mapperMethod = cachedMapperMethod(method); return mapperMethod.execute(sqlSession, args); }
总结:(1)熟习流程

    (2)代码其实不难,主要是通过学习源码温习1下jdk动态代理、反射等相干基础知识。


------分隔线----------------------------
------分隔线----------------------------

最新技术推荐