(近期在研究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; }
從中可以看出:
- hibernate默認加載就是名為hibernate.cfg.xml的配置文件,我們也可以直接調用第二個方法來指定其他配置文件;
- hibernate的配置文件實際上是通過standardServiceRegistryBuilder類去加載的,進入這個類的源碼可以看到所有的配置信息被加載到了一個類型LoadedConfig的字段中;
- 最后將一些配置項復制給了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的參數,紅色注釋標記了我們要關注的關鍵點:
- 使用properties配置信息,為什么上一步剛剛從standardServiceRegistryBuilder中把這些配置信息復制到了properties字段,這一步又把這些值重新應用回去?個人認為主要是為了讓調用者可以在這兩步中間改寫properties的值或者添加一些額外的配置信息進去。
- 根據metadataBuilder創建metadata,metadata中存儲了所有的ORM映射信息,這些映射信息來源於hibernate.cfg.xml和前面提高的metadataSources
- 根據SessionFactoryBuilder創建SessionFactory,SessionFactoryBuilder是由上一點的metadata創建。
到此,一個SessionFactory創建完畢。