VIRGIN FOREST OF JAVA
不要埋头苦干,要学习,学习,再学习。。。。。
powered by R.Zeus

Hibernate3 : org.hibernate.cfg.Configuration 解析

 

  第一次写文章,不好的地方,请口下留情哈。

  org.hibernate.cfg.Configurations 根据 xml 文件配置整个工作过程中所需要的参数。一般

我们会用 Configuration cfg = new Configuration().configure(); 创建一个配置类。那么,这句话到底做了什么呢?

  首先, new Configuration() 会做些什么呢?我们来看他的源码:

  

  protected Configuration(SettingsFactory settingsFactory) {

        System.out.println("Configuration(SettingsFactory settingsFactory)");

        this.settingsFactory = settingsFactory;

        reset();

    }

 

// 默认构造函数,先 new SettingsFactory() , 然后调用

//protected Configuration(SettingsFactory settingsFactory)

   

public Configuration() {

        this(new SettingsFactory());

}

 

reset() 初始化了很多变量,感兴趣的可以去看源代码,没有什么特别的地方。

 

  接着,调用 configure() 方法!

public Configuration configure() throws HibernateException {

        configure("/hibernate.cfg.xml");

        return this;

}

可以看出,默认使用 hibernate.cfg.xml 文件,如果想用自定义的文件,可以调用

configure(“….xml”) 方法。

public Configuration configure(String resource) throws HibernateException {

        log.debug("configuring from resource: " + resource);

        InputStream stream = getConfigurationInputStream(resource);

        return doConfigure(stream, resource);

}

根据 getConfigurationInputStream(resource) 得到文件流, getConfigurationInputStream(resource) 调用 ConfigHelper.getResourceAsStream(resource) 。

public static InputStream getResourceAsStream(String resource) {

              String stripped = resource.startsWith("/") ?

                            resource.substring(1) : resource;

              InputStream stream = null;

              ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

              if (classLoader!=null) {

                     stream = classLoader.getResourceAsStream( stripped );

              }

// 这里的代码可能应该是 stream = Environment.class.getResourceAsStream( resource );

              if ( stream == null ) {

                     Environment.class.getResourceAsStream( resource );

              }

 

              if ( stream == null ) {

                     stream = Environment.class.getClassLoader().getResourceAsStream( stripped );

              }

              if ( stream == null ) {

                     throw new HibernateException( resource + " not found" );

              }

              return stream;

       }

然后 doConfigure(stream, resource) 。

protected Configuration doConfigure(InputStream stream, String resourceName) throws HibernateException {

org.dom4j.Document doc;

        try {

            List errors = new ArrayList();

            SAXReader saxReader = xmlHelper.createSAXReader(resourceName, errors, entityResolver);

            doc = saxReader.read(new InputSource(stream));

            if (errors.size() != 0) {

                throw new MappingException(

                        "invalid configuration",

                        (Throwable) errors.get(0)

                );

            }

        }

entityResolver 在初始值为 entityResolver = XMLHelper.DEFAULT_DTD_RESOLVER ; 在 reset() 的时候设置的。 XMLHelper.DEFAULT_DTD_RESOLVE 在 XMLHelper 默认是 XMLHelper.DEFAULT_DTD_RESOLVER= new DTDEntityResolver() ; DTDEntityResolver 是用来加载 dtd 文件的。别跟我说你不知道 dtd 是什么东西?它有 3 种加载方式:

1.  文件路径以 http://hibernate.sourceforge.net/ 开头的文件,如

http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd ,

它会把 http://hibernate.sourceforge.net 去掉,加上 org/hibernate/ ,文件路径为

org/hibernate/hibernate-configuration-3.0.dtd ,然后加载这个文件。

2.       文件路径以 file:// 开头的文件,如

  file://hibernate-configuration-3.0.dtd ,

它会把 file:// 去掉,路径为 hibernate-configuration-3.0.dtd ,然后加载这个文件。

3. 如果没有以上 2 种情况,则直接加载。就是路径名没有修改过。

整个过程在 public InputSource resolveEntity(String publicId, String systemId) 中实现。

systemId 就是 dtd 的路径。大家可以去看看 SAXReader 类自带的

protected static class SAXEntityResolver ,比较比较。

 

 

在得到 doc 的值

            doc = saxReader.read(new InputSource(stream));

后,调用 protected Configuration doConfigure(org.dom4j.Document doc) ,这个函数主要是根据 doc 的到配置参数,然后存到 properties 中。

  先是设置 session-factory 的名字:

 

Element sfNode = doc.getRootElement().element("session-factory");

        String name = sfNode.attributeValue("name");

        if (name != null) {

             // 保存到 properties 中!

            properties.setProperty(Environment.SESSION_FACTORY_NAME, name);

        }

 

然后是 addProperties(sfNode) ,把 <property name=" "> </property> 保存到 properties 中。

// 这句话估计又是多余的

properties.setProperty(name, value);

 

            if (!name.startsWith("hibernate")) {

                properties.setProperty("hibernate." + name, value);

            }

接着调用了 parseSessionFactory(sfNode, name) ,把 mapping , class-cache , collection-cache , listener , event 等配置保存。到底它保存到哪,我也不全知道,只看了

protected void parseMappingElement(Element subelement, String name), 根据配置加载了 mapping 的文件,最后使用 HbmBinder : public static void bindRoot(Document doc, Mappings mappings, java.util.Map inheritedMetas) 保存。 bindRoot 是对 mapping 中的 xml 文件进行解析。

HbmBinder 和 Configuration 都有 2000 行以上的代码,在 Hibernate 中有很重要的地位。 Configuration 使用 .cfg.xml ,而 HbmBinder 则使用了 .hbm.xml 。

 

              extractRootAttributes( hmNode, mappings ) 根据 <hibernate-mapping> 的配置,把分析的结果存入 mapping 。

 

 

 

 

 

 

 

posted on 2006-08-21 21:12 R.Zeus 阅读(3021) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: