>>分享JPA、Hibernate、Mybatis对象持久化技术,对《精通JPA与Hibernate:Java对象持久化详解》提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 23660 个阅读者 刷新本主题
 * 贴子主题:  Hibernate5源码解析:SessionFactroy的创建过程 回复文章 点赞(0)  收藏  
作者:Jacky    发表时间:2020-02-24 04:32:00     消息  查看  搜索  好友  邮件  复制  引用

(近期在研究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创建完毕。



程序猿的技术大观园:www.javathinker.net



[这个贴子最后由 flybird 在 2020-02-25 10:31:00 重新编辑]
网站系统异常


系统异常信息
Request URL: http://www.javathinker.net/WEB-INF/lybbs/jsp/topic.jsp?postID=615

java.lang.NullPointerException

如果你不知道错误发生的原因,请把上面完整的信息提交给本站管理人员