Hibernate5源碼淺析(一)SessionFactory的創建過程


(近期在研究hibernate5的源碼,准備同時寫一些隨筆分享出來,也方便以后自己查找)

Hibernate5源碼淺析(一)SessionFactory的創建過程

我們調用Hibernate的第一步就是創建SessionFactory,這一步一句代碼可以寫完,但是為了分析整個過程,我們分解為以下三句:

Configuration cfg = new Configuration();//1初始化配置類
cfg.configure();//2加載配置文件
SessionFactory sf = cfg.buildSessionFactory();//3根據配置創建SessionFactory

1、初始化配置類

打開Configuration的源碼我們可以看到這個構造函數內部一共調用了以下三個方法:

    public Configuration() {
     //這里創建了一個BootstrapServiceRegistry實例傳入下一個構造函數
this( new BootstrapServiceRegistryBuilder().build() ); } public Configuration(BootstrapServiceRegistry serviceRegistry) {
    //根據傳來的值,初始化bootstrapServiceRegistry字段
this.bootstrapServiceRegistry = serviceRegistry;
    //初始化了metadataSources字段
this.metadataSources = new MetadataSources( serviceRegistry ); reset(); } 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>( );      
    //初始化standServiceRegistryBuilder字段 standardServiceRegistryBuilder
= new StandardServiceRegistryBuilder( bootstrapServiceRegistry ); entityTuplizerFactory = new EntityTuplizerFactory(); interceptor = EmptyInterceptor.INSTANCE; properties = new Properties( ); properties.putAll( standardServiceRegistryBuilder.getSettings()); }

可以看到第一步里面主要做了一些Configuration內部字段的初始化,其中我們主要關注這三個字段:bootstrapServiceRegistry、metadataSources、standardServiceRegistryBuilder。

  • bootstrapServiceRegistry  ServiceRegistry可以稱之為“服務注冊表”或“服務注冊中心”,而bootstrapServiceRegistry是hibernate中底層基礎服務注冊中心
  • metadatSources  元數據來源,可以在調用完Configuration的構造函數后通過條用Configuration的addFile、addURL、addInputStream等方法添加額外的mapping配置
  • standardServiceRegistryBuilder  標准服務注冊中心構造器,在下一步中將會用它來初始化standardServiceRegistry字段

個人理解ServiceRegistry類似Spring中的IOC容器,Hibernate將所有的底層的功能都封裝為Service注冊到ServiceRegistry中,需要的時候通過getService方法獲取即可;就像Spring中將所有的功能封裝為Bean注冊到IOC容器中,需要的時候調用getBean方法獲取。我們也可以封裝自己的Service注冊到ServiceRegistry中。關於ServiceRegistry后續再展開。

2 加載配置文件

再看第二步調用configure方法的內部執行過程

    public Configuration configure() throws HibernateException {
     //1.StandardServiceRegistryBuilder.DEFAULT_CFG_RESOURCE_NAME的值是"hibernate.cfg.xml"
return configure( StandardServiceRegistryBuilder.DEFAULT_CFG_RESOURCE_NAME ); } public Configuration configure(String resource) throws HibernateException { //2.通過這個builder來加載配置文件
     standardServiceRegistryBuilder.configure( resource );
//3.把配置文件中的設置項復制到properties字段中 properties.putAll( standardServiceRegistryBuilder.getSettings() ); return this; }

從中可以看出:

  1. hibernate默認加載就是名為hibernate.cfg.xml的配置文件,我們也可以直接調用第二個方法來指定其他配置文件;
  2. hibernate的配置文件實際上是通過standardServiceRegistryBuilder類去加載的,進入這個類的源碼可以看到所有的配置信息被加載到了一個類型LoadedConfig的字段中;
  3. 最后將一些配置項復制給了properties字段。

那么問題來了:第2點中的LoadedConfig和第3點中properties有什么區別?其實LoadedConfig包含了hibernate.cfg.xml中的所有配置項,而properties僅是其中的針對SessionFactory的Property的配置

3 創建SessionFactory

下一步是調用buildSessionFactory方法來創建SessionFactory,

    public SessionFactory buildSessionFactory() throws HibernateException {
        log.debug( "Building session factory using internal StandardServiceRegistryBuilder" );
     //使用properties重置配置信息 standardServiceRegistryBuilder.applySettings( properties );
     //構造一個standardServiceRegistry傳入下一個方法
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();
//創建SessionFactoryBuilder,然后配置它
final SessionFactoryBuilder sessionFactoryBuilder = metadata.getSessionFactoryBuilder(); if ( interceptor != null && interceptor != EmptyInterceptor.INSTANCE ) { sessionFactoryBuilder.applyInterceptor( interceptor ); } if ( getSessionFactoryObserver() != null ) { sessionFactoryBuilder.addSessionFactoryObservers( getSessionFactoryObserver() ); } if ( entityNotFoundDelegate != null ) { sessionFactoryBuilder.applyEntityNotFoundDelegate( entityNotFoundDelegate ); } if ( entityTuplizerFactory != null ) { sessionFactoryBuilder.applyEntityTuplizerFactory( entityTuplizerFactory ); }
     //根據SessionFactoryBuilder創建SessionFactory
return sessionFactoryBuilder.build(); }

這一段比較長,但是很多都是在配置Builder的參數,紅色注釋標記了我們要關注的關鍵點:

  1. 使用properties配置信息,為什么上一步剛剛從standardServiceRegistryBuilder中把這些配置信息復制到了properties字段,這一步又把這些值重新應用回去?個人認為主要是為了讓調用者可以在這兩步中間改寫properties的值或者添加一些額外的配置信息進去。
  2. 根據metadataBuilder創建metadata,metadata中存儲了所有的ORM映射信息,這些映射信息來源於hibernate.cfg.xml和前面提高的metadataSources
  3. 根據SessionFactoryBuilder創建SessionFactory,SessionFactoryBuilder是由上一點的metadata創建。

到此,一個SessionFactory創建完畢。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM