Hibernate源码解析---------hibernate.cfg.xml读取流程
通常我们使用Hibernate的时候,首先要通过以下的代码去创建一个Session.
Configuration con=new Configuration().configure(); ServiceRegistry sr=new ServiceRegistryBuilder().applySettings(con.getProperties()).buildServiceRegistry(); SessionFactory factory=con.buildSessionFactory(sr); Session session=factory.openSession(); Transaction ts=session.beginTransaction();
这里先从我们创建sessionfactory的代码入手,一级级往里看。
Configurationcon=newConfiguration().configure();
Configuration位于包org.hibernate.cfg下。该类是读取hibernate.cfg.xml文件的入口。
进入该类,我们看到1965行,
public Configuration configure() throws HibernateException { configure( "/hibernate.cfg.xml" ); return this; }
也就是说,在没有放入参数的情况下,hibernate默认会找到名字为hibernate.cfg.xml文件来进行解析。
继续往下看,找到带参数的configure()。
public Configuration configure(String resource) throws HibernateException { LOG.configuringFromResource( resource ); InputStream stream = getConfigurationInputStream( resource ); return doConfigure( stream, resource ); }
不看LOG,这里有两个方法被执行。
1.InputStreamstream=getConfigurationInputStream(resource);
2003行:
protected InputStream getConfigurationInputStream(String resource) throws HibernateException { LOG.configurationResource( resource ); return ConfigHelper.getResourceAsStream( resource ); }
继续看ConfigHelper.getResourceAsStream(resource);
ConfigHelper位于org.hibernate.internal.util。
public static InputStream getResourceAsStream(String resource) { String stripped = resource.startsWith("/") ? resource.substring(1) : resource; InputStream stream = null; ClassLoader classLoader = ClassLoaderHelper.getContextClassLoader(); if (classLoader!=null) { stream = classLoader.getResourceAsStream( stripped ); } if ( stream == null ) { stream = Environment.class.getResourceAsStream( resource ); } if ( stream == null ) { stream = Environment.class.getClassLoader().getResourceAsStream( stripped ); } if ( stream == null ) { throw new HibernateException( resource + " not found" ); } return stream; }
这里也就获取了该xml文件的stream。支线1到此结束。
2.doConfigure(stream,resource);
Configuration的2064行
protected Configuration doConfiguration(InputStream stream, String resourcesName) throws HibernateException { try{ Document document=xmlHelper.createSAXReader(errorLogger, entityResolver).read(new InputStream(stream)); /*关于这个xmlHelper是在哪里被创建的, 我花了点时间才看出来原来是构造函数里面被创建的。 Configuration有两个构造函数字:protected Configuration(SettingsFactory settingsFactory) { this.settingsFactory = settingsFactory; reset(); } public Configuration() { this( new SettingsFactory() ); } 第二个会在创建Configuration对象的时候调用第一个构造函数, 而第一个函数里面的reset()会创建所有内部的属性对象。 也就是每次创建Configuration,这些都会重置, 所以叫reset。这里学习了。 */ doConfigure(document); finally{ stream.close(); } return this; } } }
这里看一下doConfugration(Documentdoc)的代码:(2112行)
protected Configuration doConfigure(Document doc) throws HibernateException { Element sfNode = doc.getRootElement().element("session-factory"); String name=sfNode.attributeValue("name"); if(name!=null){ properties.setProperty(Environment.SESSION_FACTORY_NAME, name); } addProperties(sfNode); parseSessionFactory(sfNode, name); Element secNode=doc.getRootElement().element("security"); if(secNode!=null){ parseSecurity(secNode); } return this; }
}
终于看到我们熟悉的东西了。。T_T
在此,ElementsfNode得到了xml文件里面的<session-factory>节点内容,并在之后的方法被加入对象--addProperties(sfNode);
public Configuration addProperties(Properties extraProperties) { this.properties.putAll( extraProperties ); return this; }
properties是Configuration类的内部对象。
于是session-factory节点就这么被加进去了。
这个properties是个很重要的变量,在后面的ServiceRegistry创建的时候就会被用到。
--
可以看到这里的返回参数几乎都是Configuration,弄来弄去,最后都是在修改这个Configuration类的实例对象。
还是最初那行代码
Configurationcon=newConfiguration().configure();
说白了,这里的configure()就是调用了一大堆内部外部方法,将new出来的Configuration实例进行了加工,然后返回。。
今天先到这儿,明天继续研究,争取早点把这个图画出来,写的太乱了实在是。