ibatis_2.3源码水平浅析(待续)
题记:
总得开个头吧。前一篇垂直分析。
客户端初始化
Reader reader=null; SqlMapClient sqlMap=null; Reader =com.ibatis.common.resources.Resources.getResourceAsReader (filename); sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader); reader.close();
com.ibatis.common.resources.Resources.getResourceAsReader (filename);的方法是从当前ClassLoader里或SystemLoader里去加载名为filename的文件,并创建InputStreamReader返回。这里提下ClassLoader,JVM有Bootstrap,Ext,App的ClassLoader,用户类一般用AppClassLoader,会用Thread.getContextClassLoader()取到。关键代码如下:
private static ClassLoader getClassLoader() {// 取ContextClassLoader return Thread.currentThread().getContextClassLoader(); } public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException { InputStream in = null; if (loader != null) in = loader.getResourceAsStream(resource); if (in == null) in = ClassLoader.getSystemResourceAsStream(resource); if (in == null) throw new IOException("Could not find resource " + resource); return in; }
构建SqlMapConfigParser来做初始化工作,初始化Variables,NodeletParser(The NodeletParser is a callback based parser similar to SAX),新建SqlMapExecutorDelegate(主要执行类),SqlMapClientImpl(delegate代理类,并处理线程安全)。关键代码如下:
public SqlMapConfigParser() { this(null, null); } public SqlMapConfigParser(XmlConverter sqlMapConfigConv, XmlConverter sqlMapConv) { super(new Variables()); parser.setValidation(true); parser.setEntityResolver(new SqlMapClasspathEntityResolver());// 把有关DTD的东西放到一个private static HashMap里叫doctypeMap。 vars.sqlMapConfigConv = sqlMapConfigConv; vars.sqlMapConv = sqlMapConv; vars.delegate = new SqlMapExecutorDelegate(); vars.typeHandlerFactory = vars.delegate.getTypeHandlerFactory(); vars.client = new SqlMapClientImpl(vars.delegate); registerDefaultTypeAliases(); // 调用typeHandlerFactory,关联关键类类型 addSqlMapConfigNodelets(); addGlobalPropNodelets(); addSettingsNodelets(); addTypeAliasNodelets(); addTypeHandlerNodelets(); addTransactionManagerNodelets(); addSqlMapNodelets(); addResultObjectFactoryNodelets(); }
在这里SqlMapExecutorDelegate()初始化是重点,他需要初始化XML-CONFIG中所有的关键数据,并且存储和处理由NodeletParser来做。
XML配置文件解析思路
ibatis解析XML是的DOM模型,NodeletParser实现了一个类似以"/Father/Child"字符串为key,匿名new Nodelet()类为value(匿名Nodelet类定义好自己的 public void process(Node node)方法)的回调函数 。当在解析XML的时候,根据当前解析到的某个node,并取得node的getNodeName,getAttributes,getChildNodes为key,来调用相应的回调函数。父子关系则为/Father/Child这种来标识,attribute则为:/Father/@attri1@attri2。
这种处理XML的方式对我来说还是挺陌生的,正好自己的“小爬虫”里运用运用。而且假如需要更改XML中某个NodeName的时候,只需要更改Map的相应Key的值,而不用更改处理逻辑,让人感觉很简约。