`
u013830484
  • 浏览: 4510 次
社区版块
存档分类
最新评论

Hibernate源码分析2

阅读更多
再扯二句蛋:距离上一次写博客已经过了将近半个月了,因为公司的活比较多,一直没有时间研究(实际上一直都有很多活),元旦还出去浪了一圈,这个周末再来写一点`
上回大致把hibernate的启动加载配置的过程说了一遍,说到了XClass和保存的集合MetadataSourceQueue,这两个东西我暂时不想说(其实没有研究明白,怕说不好),我觉得研究hibernate框架可以从两头开始,一个是入口,也就是上一篇的启动加载过程,一个是出口,也就是我们经常调用的接口方法和类,今天从出口来讲一下,以后再将两头串起来。。。

我们常使用的接口要算是SessionFactory 了:
SessionFactory factory = cfg.buildSessionFactory();
buildSessionFactory中实际上返回的对象是SessionFactoryImpl,而SessionFactoryImpl实现了SessionFactoryImplementor接口,而SessionFactoryImplementor这个接口又继承了SessionFactory这个接口,SessionFactoryImpl实际上就是一个SessionFactory,为何需要在他们中间横插一个SessionFactoryImplementor?研究!

实际上这个不带参数的buildSessionFactory()最终调用的是带参的buildSessionFactory(ServiceRegistry serviceRegistry),这个方法返回了最终的SessionFactoryImp:
new SessionFactoryImpl(
    this,
    mapping,
    serviceRegistry,
    settings,
    sessionFactoryObserver
   );

接着往下走,话说SessionFactory的getCurrentSession方法将返回我们最终使用的Session,且看SessionFactory中的getCurrentSession方法做了什么,上源码:
if ( currentSessionContext == null ) {
   throw new HibernateException( "No CurrentSessionContext configured!" );
  }
  return currentSessionContext.currentSession();
显然是用了currentSessionContext.currentSession() 这个东西来获得的,其实 SeesionFactory本身并没有Session,而是用的是currentSessionContext 的Session!那么currentSessionContext 是啥?就是CurrentSessionContext类,从名字上就知道意思了:当前Session上下文,做了这么久的代码,上下文的意思应该知道吧
好了,再看看currentSessionContext 到底是何方神圣:currentSessionContext = buildCurrentSessionContext();
buildCurrentSessionContext这个方法做了啥?上源码:
private CurrentSessionContext buildCurrentSessionContext() {
  String impl = properties.getProperty( Environment.CURRENT_SESSION_CONTEXT_CLASS );
  // for backward-compatibility
  if ( impl == null ) {
   if ( canAccessTransactionManager() ) {
    impl = "jta";
   }
   else {
    return null;
   }
  }
  if ( "jta".equals( impl ) ) {
   if ( ! transactionFactory().compatibleWithJtaSynchronization() ) {
    LOG.autoFlushWillNotWork();
   }
   return new JTASessionContext( this );
  }
  else if ( "thread".equals( impl ) ) {
   return new ThreadLocalSessionContext( this );
  }
  else if ( "managed".equals( impl ) ) {
   return new ManagedSessionContext( this );
  }
  else {
   try {
    Class implClass = serviceRegistry.getService( ClassLoaderService.class ).classForName( impl );
    return ( CurrentSessionContext ) implClass
      .getConstructor( new Class[] { SessionFactoryImplementor.class } )
      .newInstance( this );
   }
   catch( Throwable t ) {
    LOG.unableToConstructCurrentSessionContext( impl, t );
    return null;
   }
  }
}
看到没有: String impl = properties.getProperty( Environment.CURRENT_SESSION_CONTEXT_CLASS );回去试着去获取我们配置的信息
(题外话,配置的获取
  this.properties = new Properties();
  this.properties.putAll( cfg.getProperties() );

Environment.CURRENT_SESSION_CONTEXT_CLASS是 :public static final String CURRENT_SESSION_CONTEXT_CLASS = "hibernate.current_session_context_class";(在AvailableSettings中)
题外话:Environment implements AvailableSettings用来表示各种配置常量,这里的Environment 是hibernate自己的类,不是org.omg.CORBA.Environment !
看,如果我们再配置文件中将hibernate.current_session_context_class配置成thread就是返回的是ThreadLocalSessionContext(线程绑定的上下文),如果我们啥都不配的话,默认就是JTASessionContext(JTA的上下文),至于线程和JTA的含义,就属于另外讨论的话题了,有时间再研究
ok,假设我们就啥都没有配吧,就用的是JTASessionContext吧,顺着这个线走下去吧(解决主要矛盾嘛),那么肯定要来看看JTASessionContext的源码咯!首先我们很快就会发现各个SessionContext都会继承自一个抽象类:AbstractCurrentSessionContext,而AbstractCurrentSessionContext则是AbstractCurrentSessionContext implements CurrentSessionContext,
然后当然首要的是currentSession方法了,上源码:
@Override
public Session currentSession() throws HibernateException {
  final JtaPlatform jtaPlatform = factory().getServiceRegistry().getService( JtaPlatform.class );
  final TransactionManager transactionManager = jtaPlatform.retrieveTransactionManager();
  if ( transactionManager == null ) {
   throw new HibernateException( "No TransactionManagerLookup specified" );
  }
  Transaction txn;
  try {
   txn = transactionManager.getTransaction();
   if ( txn == null ) {
    throw new HibernateException( "Unable to locate current JTA transaction" );
   }
   if ( !JtaStatusHelper.isActive( txn.getStatus() ) ) {
    // We could register the session against the transaction even though it is
    // not started, but we'd have no guarantee of ever getting the map
    // entries cleaned up (aside from spawning threads).
    throw new HibernateException( "Current transaction is not in progress" );
   }
  }
  catch ( HibernateException e ) {
   throw e;
  }
  catch ( Throwable t ) {
   throw new HibernateException( "Problem locating/validating JTA transaction", t );
  }
  final Object txnIdentifier = jtaPlatform.getTransactionIdentifier( txn );
  Session currentSession = ( Session ) currentSessionMap.get( txnIdentifier );
  if ( currentSession == null ) {
   currentSession = buildOrObtainSession();
   try {
    txn.registerSynchronization( buildCleanupSynch( txnIdentifier ) );
   }
   catch ( Throwable t ) {
    try {
     currentSession.close();
    }
    catch ( Throwable ignore ) {
     LOG.debug( "Unable to release generated current-session on failed synch registration", ignore );
    }
    throw new HibernateException( "Unable to register cleanup Synchronization with TransactionManager" );
   }
   currentSessionMap.put( txnIdentifier, currentSession );
  }
  else {
   validateExistingSession( currentSession );
  }
  return currentSession;
}

其中,factory()是父类(AbstractCurrentSessionContext )的方法,只是:
public SessionFactoryImplementor factory() {
  return factory;
}
factory而已,这个factory是啥??
还记得SessionFactoryImp中buildCurrentSessionContext方法的return new JTASessionContext( this );吗?这个factory就是this(SessionFactoryImp实例)
final JtaPlatform jtaPlatform = factory().getServiceRegistry().getService( JtaPlatform.class );中 factory().getServiceRegistry()返回的是SessionFactoryImp的变量serviceRegistry,何处来的?
还记得我们在Configuration中new SessionFactoryImp的时候吗?
new SessionFactoryImpl(
    this,
    mapping,
    serviceRegistry,
    settings,
    sessionFactoryObserver
   )

上述的的这个不带参数的buildSessionFactory()最终调用的是带参的buildSessionFactory(ServiceRegistry serviceRegistry)的调用之前buildSessionFactory方法中做了:
final ServiceRegistry serviceRegistry =  new ServiceRegistryBuilder()
    .applySettings( properties )
    .buildServiceRegistry();
applySettings( properties )是将hibernate.properties产生的Properties对象传递给ServiceRegistryBuilder,而buildServiceRegistry方法则是发生事情的地方:
public ServiceRegistry buildServiceRegistry() {
  Map<?,?> settingsCopy = new HashMap();
  settingsCopy.putAll( settings );
  Environment.verifyProperties( settingsCopy );
  ConfigurationHelper.resolvePlaceHolders( settingsCopy );
  for ( Integrator integrator : bootstrapServiceRegistry.getService( IntegratorService.class ).getIntegrators() ) {
   if ( ServiceContributingIntegrator.class.isInstance( integrator ) ) {
    ServiceContributingIntegrator.class.cast( integrator ).prepareServices( this );
   }
  }
  return new StandardServiceRegistryImpl( bootstrapServiceRegistry, initiators, providedServices, settingsCopy );
}
这就是我们得到SessionFactory的大致过程,其中的几个细节值得研究:
1:我们只是知道了要传入ServiceRegistry ,那是做啥的?
2:SessionFactoryImplementor的意义
这次先到这里,下回就解决这些细节问题,那么入口和出口的大致流程就完事儿了```
0
4
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics