Hibernate3 : org.hibernate.cfg.Configuration解析

来源:互联网 发布:文本校对软件 编辑:程序博客网 时间:2024/04/30 05:51
 

 

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

  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_RESOLVEXMLHelper默认是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),把mappingclass-cachecollection-cachelistener 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文件进行解析。

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

 

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