mybatis源碼總結--快速入門
來源:程序員人生 發布時間:2014-12-23 08:24:49 閱讀次數:3198次
首先在此聲明,本人是通過學習湖畔微風《深入淺出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動態代理、反射等相干基礎知識。
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈