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创建完毕。

 

posted @ 2017-11-14 14:31  kuntaljy  阅读(2913)  评论(2编辑  收藏  举报