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

  • 相关阅读:
    masonry中的make,remake,update
    内存划分五大区
    Java处理JPEG图片时,需要导入com.sun.image.codec.jpeg.JPEGImageEn,报错处理
    Xcode 8 控制台输出大量不用的log的问题解决&&NSLog失效的解决
    GCD系列 之(二): 多核心的性能
    GCD系列 之(一):基本概念和Dispatch Queue
    CADisplayLink使用中的循环引用问题的解决
    定时帧:NSTimer和CADisplayLink
    设置圆角的4种方式--引申出离屏渲染
    华为OLT 注册过程
  • 原文地址:https://www.cnblogs.com/ArtofDesign/p/7831904.html
Copyright © 2020-2023  润新知