咱们要使用 Hibernate 的功能,首先须要读取 Hibernate 的配置文件,根据配置启动 Hibernate ,而后建立 SessionFactory。sql
建立 SessionFactory 的代码很简单,这也是咱们要分析的代码:bootstrap
Configuration cfg = new Configuration().configure(); SessionFactory factory = cfg.buildSessionFactory();
接下来,就针对这两行代码进行分析。缓存
首先,咱们来看看初始化 Configuration
实例的源码中都作了些什么:网络
public Configuration() { this( new BootstrapServiceRegistryBuilder().build() ); }
无参构造器调用了重载的构造器,接着看重载的构造器,Configuration.class 第121行:session
public Configuration(BootstrapServiceRegistry serviceRegistry) { this.bootstrapServiceRegistry = serviceRegistry; this.metadataSources = new MetadataSources( serviceRegistry ); reset(); }
在这个构造器中,有个reset()
方法咱们等下再看。咱们先来看看传入的参数 serviceRegistry
,以及初始化的两个成员属性:app
BootstrapServiceRegistry
是个接口,翻译过来是“启动服务注册器”,是 Hibernate 底层的的基础服务注册器。MetadataSources
元数据来源,构造器接收了 BootstrapServiceRegistry
的实例看一下这个构造器的源码,MeatadataSources.class 第 77 行:ide
// 使用指定的服务注册器实例建立一个 Metadata “元数据的源” public MetadataSources(ServiceRegistry serviceRegistry) { // 传入的参数还只能是 BootstrapServiceRegistry 或 StandardServiceRegistry 类型的实例 if ( ! isExpectedServiceRegistryType( serviceRegistry ) ) { LOG.debugf( "Unexpected ServiceRegistry type [%s] encountered during building of MetadataSources; may cause " + "problems later attempting to construct MetadataBuilder", serviceRegistry.getClass().getName() ); } this.serviceRegistry = serviceRegistry; this.xmlMappingBinderAccess = new XmlMappingBinderAccess( serviceRegistry ); }
好像看不太明白,那咱们来看看这个 MetadataSource
类的说明注释:ui
Entry point into working with sources of metadata information (mapping XML, annotations). Tell Hibernate about sources and then call buildMetadata() , or use getMetadataBuilder() to customize how sources are processed (naming strategies, etc).this
加载元数据信息(通常是XML文件、注解中配置的映射)。Hibernate 加载该信息以后,经过调用 buildMetadata() 或者 getMetadataBuilder() 方法来肯定整个 Hibernate 运行时环境的执行策略。url
看到这里,能够认为 MetadataSource
的就是用来加载配置信息的。其实在 Metadata 中,就存储了 ORM 的映射信息。
构造方法的最后一行代码:
this.xmlMappingBinderAccess = new XmlMappingBinderAccess( serviceRegistry );
咱们继续跟踪看看 XmlMappingBinderAccess
的构造方法作了些什么:
public XmlMappingBinderAccess(ServiceRegistry serviceRegistry) { this.classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); // NOTE : 参数中的 boolean 值表示在加载 XML 文件时是否执行验证。 // 在这里显式指定为true,可让运行时的 JAXP(XML处理的Java API)和 JAXB(根据XML生成Java类)启动速度更快, // 若是不验证 XML,可能会由于 XML 中的一些小错误而致使大麻烦。 this.mappingBinder = new MappingBinder( serviceRegistry.getService( ClassLoaderService.class ), true ); }
好了,咱们如今知道这行代码是在作 XML 文件中绑定映射初始化相关的处理。
继续回到 Configuration(BootstrapServiceRegistry serviceRegistry)
重载构造器中。
先简单说明一下 Hibernate 中的 Service:
BootstrapServiceRegistry
接口的父接口是ServiceRegistry
,这个接口的父接口是Service
。
Hibernate 将全部的底层的功能都封装为Service
注册到 ServiceRegistry 中,须要的时候经过 getService() 方法获取便可。
刚刚留下了一行 reset()
方法没有看,咱们如今来看看,Configuration.class 第 149 行:
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>( ); // 初始化 standardServiceRegistryBuilder 成员变量 standardServiceRegistryBuilder = new StandardServiceRegistryBuilder( bootstrapServiceRegistry ); entityTuplizerFactory = new EntityTuplizerFactory(); interceptor = EmptyInterceptor.INSTANCE; properties = new Properties( ); properties.putAll( standardServiceRegistryBuilder.getSettings()); }
implicitNamingStrategy
和 physicalNamingStrategy
就是 Hibernate 的命名策略相关的实例:
implicitNamingStrategy
:隐式命名策略physicalNamingStrategy
:物理命名策略命名策略有多种实现方式:Hibernate 标准,JPA 标准。能够调用 Configuration 对象的 setImplicitNamingStrategy()
和 setPhysicalNamingStrategy()
方法设置命名策略。
引用一张图片,显示了 Hibernate 5.x 中的命名策略的关系:
在这里先不对命名策略作太细化的研究,咱们接着看下面几行代码中的 HashMap 实例分别表明什么:
<query>
元素的内容或注解,该元素用于定义 HQL 语句<sql-query>
元素的内容或注解,该元素用于定义 SQL 语句我对 reset() 方法小结一下:重置初始化了另外一些成员变量(囧)
至此,Configuration
的初始化过程就已经完成了。
接着调用 Configuration
对象的 configure()
方法,能够重载该方法指定配置文件的资源路径。
咱们先来看看无参的方法:
// 在程序的资源路径下,读取文件名为 hibernate.cfg.xml 映射配置文件 public Configuration configure() throws HibernateException { return configure( StandardServiceRegistryBuilder.DEFAULT_CFG_RESOURCE_NAME ); }
再来看看有参的方法:
// 读取符合 hibernate-configuration-3.0.dtd 文档类型规范的配置文件 public Configuration configure(String resource) throws HibernateException { standardServiceRegistryBuilder.configure( resource ); // ... properties.putAll( standardServiceRegistryBuilder.getSettings() ); return this; }
咱们能够发现, configure() 方法内部调用了 standardServiceRegistryBuilder.configure( resource );
,若是咱们只是使用 Configuration 对象,那么这个方法就没有做用,这里咱们仍是追踪了看一下,追踪到类 StandardServiceRegistryBuilder
,看看其中的 configure() 作了什么处理:
// 从指定的资源位置,读取 XML 文件获取配置信息(经常使用) public StandardServiceRegistryBuilder configure(String resourceName) { return configure( configLoader.loadConfigXmlResource( resourceName ) ); } // 指定 File 对象 public StandardServiceRegistryBuilder configure(File configurationFile) { return configure( configLoader.loadConfigXmlFile( configurationFile ) ); } // 能够获取网络上的指定路径URL public StandardServiceRegistryBuilder configure(URL url) { return configure( configLoader.loadConfigXmlUrl( url ) ); } // 有多个 cfg.xml 文件时,合并它们 public StandardServiceRegistryBuilder configure(LoadedConfig loadedConfig) { aggregatedCfgXml.merge( loadedConfig ); settings.putAll( loadedConfig.getConfigurationValues() ); return this; }
最终返回了 StandardServiceRegistryBuilder
对象,这个对象用做 Hibernate 5.x 中建立 SessionFactory。关于 Hibernate 5.x 的建立方式,将在另外一篇文章中讲解。
接下来,看咱们要分析的第二行代码:
SessionFactory factory = cfg.buildSessionFactory();
调用 Configuration 对象的 buildSessionFactory()
方法。咱们进到这个方法看看里面是什么:
// 使用当前 configuration 配置对象中的配置信息建立一个 SessionFactory 实例,该实例被建立后就不会再改变 // 此后再对 configuration 作修改也不会影响到已建立的 SessionFactory 实例 public SessionFactory buildSessionFactory() throws HibernateException { log.debug( "Building session factory using internal StandardServiceRegistryBuilder" ); // ----- 一、使用 properties 重置配置属性 ----- standardServiceRegistryBuilder.applySettings( properties ); 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(); // 使用 Metadata 对象的 getSessionFactoryBuilder() 建立 SessionFactoryBuilder final SessionFactoryBuilder sessionFactoryBuilder = metadata.getSessionFactoryBuilder(); if ( interceptor != null && interceptor != EmptyInterceptor.INSTANCE ) { sessionFactoryBuilder.applyInterceptor( interceptor ); } if ( getSessionFactoryObserver() != null ) { // 为 SessionFactory 添加观察者 Observers sessionFactoryBuilder.addSessionFactoryObservers( getSessionFactoryObserver() ); } if ( getEntityNotFoundDelegate() != null ) { sessionFactoryBuilder.applyEntityNotFoundDelegate( getEntityNotFoundDelegate() ); } if ( getEntityTuplizerFactory() != null ) { sessionFactoryBuilder.applyEntityTuplizerFactory( getEntityTuplizerFactory() ); } if ( getCurrentTenantIdentifierResolver() != null ) { sessionFactoryBuilder.applyCurrentTenantIdentifierResolver( getCurrentTenantIdentifierResolver() ); } // 四、建立并返回 SessionFactory 实例 return sessionFactoryBuilder.build(); }
buildSessionFactory()
方法的内容比较多,可是主要就是3个核心步骤:
至此,Hibernate 5.x 建立 SessionFactory 的源码所有走完。