|
(近期在研究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 重新编辑]
|
|