zoukankan      html  css  js  c++  java
  • 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创建完毕。

  • 相关阅读:
    如何通过命令行窗口查看sqlite数据库文件
    eclipse自动补全的设置
    文本装饰
    注释和特殊符号
    文本装饰
    网页背景
    通过ArcGIS Server admin 查看和删除已注册的 Web Adaptor
    通过 ArcGIS Server Manager 查看已安装的 Web Adaptor
    通过 ArcGIS Server Manager 验证 DataStore
    Windows上安装ArcGIS Enterprise——以 Windows Server 2012 R2上安装 ArcGIS 10.8为例
  • 原文地址:https://www.cnblogs.com/ArtofDesign/p/7831904.html
Copyright © 2011-2022 走看看