咱們要使用 Hibernate 的功能,首先須要讀取 Hibernate 的配置文件,根據配置啓動 Hibernate ,而後建立 SessionFactory。sql
建立 SessionFactory 的代碼很簡單,這也是咱們要分析的代碼:bootstrap
Configuration cfg = new Configuration().configure(); SessionFactory factory = cfg.buildSessionFactory();
接下來,就針對這兩行代碼進行分析。緩存
首先,咱們來看看初始化 Configuration
實例的源碼中都作了些什麼:網絡
public Configuration() { this( new BootstrapServiceRegistryBuilder().build() ); }
無參構造器調用了重載的構造器,接着看重載的構造器,Configuration.class 第121行:session
public Configuration(BootstrapServiceRegistry serviceRegistry) { this.bootstrapServiceRegistry = serviceRegistry; this.metadataSources = new MetadataSources( serviceRegistry ); reset(); }
在這個構造器中,有個reset()
方法咱們等下再看。咱們先來看看傳入的參數 serviceRegistry
,以及初始化的兩個成員屬性:app
BootstrapServiceRegistry
是個接口,翻譯過來是「啓動服務註冊器」,是 Hibernate 底層的的基礎服務註冊器。MetadataSources
元數據來源,構造器接收了 BootstrapServiceRegistry
的實例看一下這個構造器的源碼,MeatadataSources.class 第 77 行:ide
// 使用指定的服務註冊器實例建立一個 Metadata 「元數據的源」 public MetadataSources(ServiceRegistry serviceRegistry) { // 傳入的參數還只能是 BootstrapServiceRegistry 或 StandardServiceRegistry 類型的實例 if ( ! isExpectedServiceRegistryType( serviceRegistry ) ) { LOG.debugf( "Unexpected ServiceRegistry type [%s] encountered during building of MetadataSources; may cause " + "problems later attempting to construct MetadataBuilder", serviceRegistry.getClass().getName() ); } this.serviceRegistry = serviceRegistry; this.xmlMappingBinderAccess = new XmlMappingBinderAccess( serviceRegistry ); }
好像看不太明白,那咱們來看看這個 MetadataSource
類的說明註釋:ui
Entry point into working with sources of metadata information (mapping XML, annotations). Tell Hibernate about sources and then call buildMetadata() , or use getMetadataBuilder() to customize how sources are processed (naming strategies, etc).this
加載元數據信息(通常是XML文件、註解中配置的映射)。Hibernate 加載該信息以後,經過調用 buildMetadata() 或者 getMetadataBuilder() 方法來肯定整個 Hibernate 運行時環境的執行策略。url
看到這裏,能夠認爲 MetadataSource
的就是用來加載配置信息的。其實在 Metadata 中,就存儲了 ORM 的映射信息。
構造方法的最後一行代碼:
this.xmlMappingBinderAccess = new XmlMappingBinderAccess( serviceRegistry );
咱們繼續跟蹤看看 XmlMappingBinderAccess
的構造方法作了些什麼:
public XmlMappingBinderAccess(ServiceRegistry serviceRegistry) { this.classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); // NOTE : 參數中的 boolean 值表示在加載 XML 文件時是否執行驗證。 // 在這裏顯式指定爲true,可讓運行時的 JAXP(XML處理的Java API)和 JAXB(根據XML生成Java類)啓動速度更快, // 若是不驗證 XML,可能會由於 XML 中的一些小錯誤而致使大麻煩。 this.mappingBinder = new MappingBinder( serviceRegistry.getService( ClassLoaderService.class ), true ); }
好了,咱們如今知道這行代碼是在作 XML 文件中綁定映射初始化相關的處理。
繼續回到 Configuration(BootstrapServiceRegistry serviceRegistry)
重載構造器中。
先簡單說明一下 Hibernate 中的 Service:
BootstrapServiceRegistry
接口的父接口是ServiceRegistry
,這個接口的父接口是Service
。
Hibernate 將全部的底層的功能都封裝爲Service
註冊到 ServiceRegistry 中,須要的時候經過 getService() 方法獲取便可。
剛剛留下了一行 reset()
方法沒有看,咱們如今來看看,Configuration.class 第 149 行:
protected void reset() { implicitNamingStrategy = ImplicitNamingStrategyJpaCompliantImpl.INSTANCE; physicalNamingStrategy = PhysicalNamingStrategyStandardImpl.INSTANCE; namedQueries = new HashMap<String,NamedQueryDefinition>(); namedSqlQueries = new HashMap<String,NamedSQLQueryDefinition>(); sqlResultSetMappings = new HashMap<String, ResultSetMappingDefinition>(); namedEntityGraphMap = new HashMap<String, NamedEntityGraphDefinition>(); namedProcedureCallMap = new HashMap<String, NamedProcedureCallDefinition>( ); // 初始化 standardServiceRegistryBuilder 成員變量 standardServiceRegistryBuilder = new StandardServiceRegistryBuilder( bootstrapServiceRegistry ); entityTuplizerFactory = new EntityTuplizerFactory(); interceptor = EmptyInterceptor.INSTANCE; properties = new Properties( ); properties.putAll( standardServiceRegistryBuilder.getSettings()); }
implicitNamingStrategy
和 physicalNamingStrategy
就是 Hibernate 的命名策略相關的實例:
implicitNamingStrategy
:隱式命名策略physicalNamingStrategy
:物理命名策略命名策略有多種實現方式:Hibernate 標準,JPA 標準。能夠調用 Configuration 對象的 setImplicitNamingStrategy()
和 setPhysicalNamingStrategy()
方法設置命名策略。
引用一張圖片,顯示了 Hibernate 5.x 中的命名策略的關係:
在這裏先不對命名策略作太細化的研究,咱們接着看下面幾行代碼中的 HashMap 實例分別表明什麼:
<query>
元素的內容或註解,該元素用於定義 HQL 語句<sql-query>
元素的內容或註解,該元素用於定義 SQL 語句我對 reset() 方法小結一下:重置初始化了另外一些成員變量(囧)
至此,Configuration
的初始化過程就已經完成了。
接着調用 Configuration
對象的 configure()
方法,能夠重載該方法指定配置文件的資源路徑。
咱們先來看看無參的方法:
// 在程序的資源路徑下,讀取文件名爲 hibernate.cfg.xml 映射配置文件 public Configuration configure() throws HibernateException { return configure( StandardServiceRegistryBuilder.DEFAULT_CFG_RESOURCE_NAME ); }
再來看看有參的方法:
// 讀取符合 hibernate-configuration-3.0.dtd 文檔類型規範的配置文件 public Configuration configure(String resource) throws HibernateException { standardServiceRegistryBuilder.configure( resource ); // ... properties.putAll( standardServiceRegistryBuilder.getSettings() ); return this; }
咱們能夠發現, configure() 方法內部調用了 standardServiceRegistryBuilder.configure( resource );
,若是咱們只是使用 Configuration 對象,那麼這個方法就沒有做用,這裏咱們仍是追蹤了看一下,追蹤到類 StandardServiceRegistryBuilder
,看看其中的 configure() 作了什麼處理:
// 從指定的資源位置,讀取 XML 文件獲取配置信息(經常使用) public StandardServiceRegistryBuilder configure(String resourceName) { return configure( configLoader.loadConfigXmlResource( resourceName ) ); } // 指定 File 對象 public StandardServiceRegistryBuilder configure(File configurationFile) { return configure( configLoader.loadConfigXmlFile( configurationFile ) ); } // 能夠獲取網絡上的指定路徑URL public StandardServiceRegistryBuilder configure(URL url) { return configure( configLoader.loadConfigXmlUrl( url ) ); } // 有多個 cfg.xml 文件時,合併它們 public StandardServiceRegistryBuilder configure(LoadedConfig loadedConfig) { aggregatedCfgXml.merge( loadedConfig ); settings.putAll( loadedConfig.getConfigurationValues() ); return this; }
最終返回了 StandardServiceRegistryBuilder
對象,這個對象用做 Hibernate 5.x 中建立 SessionFactory。關於 Hibernate 5.x 的建立方式,將在另外一篇文章中講解。
接下來,看咱們要分析的第二行代碼:
SessionFactory factory = cfg.buildSessionFactory();
調用 Configuration 對象的 buildSessionFactory()
方法。咱們進到這個方法看看裏面是什麼:
// 使用當前 configuration 配置對象中的配置信息建立一個 SessionFactory 實例,該實例被建立後就不會再改變 // 此後再對 configuration 作修改也不會影響到已建立的 SessionFactory 實例 public SessionFactory buildSessionFactory() throws HibernateException { log.debug( "Building session factory using internal StandardServiceRegistryBuilder" ); // ----- 一、使用 properties 重置配置屬性 ----- standardServiceRegistryBuilder.applySettings( properties ); return buildSessionFactory( standardServiceRegistryBuilder.build() ); } public SessionFactory buildSessionFactory(ServiceRegistry serviceRegistry) throws HibernateException { log.debug( "Building session factory using provided StandardServiceRegistry" ); // ----- 二、建立 MetadataBuilder ,而後作一些配置工做 ----- final MetadataBuilder metadataBuilder = metadataSources .getMetadataBuilder( (StandardServiceRegistry) serviceRegistry ); // 設置默認的隱式命名策略 if ( implicitNamingStrategy != null ) { metadataBuilder.applyImplicitNamingStrategy( implicitNamingStrategy ); } // 設置默認的物理命名策略 if ( physicalNamingStrategy != null ) { metadataBuilder.applyPhysicalNamingStrategy( physicalNamingStrategy ); } // 設置共享緩存模式 if ( sharedCacheMode != null ) { metadataBuilder.applySharedCacheMode( sharedCacheMode ); } if ( !typeContributorRegistrations.isEmpty() ) { for ( TypeContributor typeContributor : typeContributorRegistrations ) { metadataBuilder.applyTypes( typeContributor ); } } if ( !basicTypes.isEmpty() ) { for ( BasicType basicType : basicTypes ) { metadataBuilder.applyBasicType( basicType ); } } if ( sqlFunctions != null ) { for ( Map.Entry<String, SQLFunction> entry : sqlFunctions.entrySet() ) { metadataBuilder.applySqlFunction( entry.getKey(), entry.getValue() ); } } if ( auxiliaryDatabaseObjectList != null ) { for ( AuxiliaryDatabaseObject auxiliaryDatabaseObject : auxiliaryDatabaseObjectList ) { metadataBuilder.applyAuxiliaryDatabaseObject( auxiliaryDatabaseObject ); } } if ( attributeConverterDefinitionsByClass != null ) { for ( AttributeConverterDefinition attributeConverterDefinition : attributeConverterDefinitionsByClass.values() ) { metadataBuilder.applyAttributeConverter( attributeConverterDefinition ); } } // ----- 三、使用 MetadataBuilder 建立 Metadata 實例 ----- final Metadata metadata = metadataBuilder.build(); // 使用 Metadata 對象的 getSessionFactoryBuilder() 建立 SessionFactoryBuilder final SessionFactoryBuilder sessionFactoryBuilder = metadata.getSessionFactoryBuilder(); if ( interceptor != null && interceptor != EmptyInterceptor.INSTANCE ) { sessionFactoryBuilder.applyInterceptor( interceptor ); } if ( getSessionFactoryObserver() != null ) { // 爲 SessionFactory 添加觀察者 Observers sessionFactoryBuilder.addSessionFactoryObservers( getSessionFactoryObserver() ); } if ( getEntityNotFoundDelegate() != null ) { sessionFactoryBuilder.applyEntityNotFoundDelegate( getEntityNotFoundDelegate() ); } if ( getEntityTuplizerFactory() != null ) { sessionFactoryBuilder.applyEntityTuplizerFactory( getEntityTuplizerFactory() ); } if ( getCurrentTenantIdentifierResolver() != null ) { sessionFactoryBuilder.applyCurrentTenantIdentifierResolver( getCurrentTenantIdentifierResolver() ); } // 四、建立並返回 SessionFactory 實例 return sessionFactoryBuilder.build(); }
buildSessionFactory()
方法的內容比較多,可是主要就是3個核心步驟:
至此,Hibernate 5.x 建立 SessionFactory 的源碼所有走完。