Spring源代码解析(八):Spring驱动Hibernate的实现.doc_第1页
Spring源代码解析(八):Spring驱动Hibernate的实现.doc_第2页
Spring源代码解析(八):Spring驱动Hibernate的实现.doc_第3页
Spring源代码解析(八):Spring驱动Hibernate的实现.doc_第4页
Spring源代码解析(八):Spring驱动Hibernate的实现.doc_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

O/R工具出现之后,简化了许多复杂的信息持久化的开发。Spring应用开发者可以通过Spring提供的O/R方案更方便的使用各种持久化工具,比如Hibernate;下面我们就Spring+Hibernate中的Spring实现做一个简单的剖析。Spring对Hinberanate的配置是通过LocalSessionFactoryBean来完成的,这是一个工厂Bean的实现,在基类AbstractSessionFactoryBean中:Java代码 /* * 这是FactoryBean需要实现的接口方法,直接取得当前的sessionFactory的值 */public Object getObject() return this.sessionFactory;这个值在afterPropertySet中定义:Java代码 public void afterPropertiesSet() throws Exception /这个buildSessionFactory是通过配置信息得到SessionFactory的地方SessionFactory rawSf = buildSessionFactory();/这里使用了Proxy方法插入对getCurrentSession的拦截,得到和事务相关的sessionthis.sessionFactory = wrapSessionFactoryIfNecessary(rawSf);我们先看看SessionFactory是怎样创建的,这个方法很长,包含了创建Hibernate的SessionFactory的详尽步骤:Java代码 protected SessionFactory buildSessionFactory() throws Exception SessionFactory sf = null;/ Create Configuration instance.Configuration config = newConfiguration();/这里配置数据源,事务管理器,LobHander到Holder中,这个Holder是一个ThreadLocal变量,这样这些资源就和线程绑定了if (this.dataSource != null) / Make given DataSource available for SessionFactory configuration.configTimeDataSourceHolder.set(this.dataSource);if (this.jtaTransactionManager != null) / Make Spring-provided JTA TransactionManager available.configTimeTransactionManagerHolder.set(this.jtaTransactionManager);if (this.lobHandler != null) / Make given LobHandler available for SessionFactory configuration./ Do early because because mapping resource might refer to custom types.configTimeLobHandlerHolder.set(this.lobHandler);/这里是使用Hibernate的各个属性的配置,这里使用了Configuration类来抽象这些数据try / Set connection release mode on_close as default./ This was the case for Hibernate 3.0; Hibernate 3.1 changed/ it to auto (i.e. after_statement or after_transaction)./ However, for Springs resource management (in particular for/ HibernateTransactionManager), on_close is the better default.config.setProperty(Environment.RELEASE_CONNECTIONS, ConnectionReleaseMode.ON_CLOSE.toString();if (!isExposeTransactionAwareSessionFactory() / Not exposing a SessionFactory proxy with transaction-aware/ getCurrentSession() method - set Hibernate 3.1 CurrentSessionContext/ implementation instead, providing the Spring-managed Session that way./ Can be overridden by a custom value for corresponding Hibernate property.config.setProperty(Environment.CURRENT_SESSION_CONTEXT_CLASS,org.springframework.orm.hibernate3.SpringSessionContext);if (this.entityInterceptor != null) / Set given entity interceptor at SessionFactory level.config.setInterceptor(this.entityInterceptor);if (this.namingStrategy != null) / Pass given naming strategy to Hibernate Configuration.config.setNamingStrategy(this.namingStrategy);if (this.typeDefinitions != null) / Register specified Hibernate type definitions.Mappings mappings = config.createMappings();for (int i = 0; i this.typeDefinitions.length; i+) TypeDefinitionBean typeDef = this.typeDefinitionsi;mappings.addTypeDef(typeDef.getTypeName(), typeDef.getTypeClass(), typeDef.getParameters();if (this.filterDefinitions != null) / Register specified Hibernate FilterDefinitions.for (int i = 0; i this.filterDefinitions.length; i+) config.addFilterDefinition(this.filterDefinitionsi);if (this.configLocations != null) for (int i = 0; i this.configLocations.length; i+) / Load Hibernate configuration from given location.config.configure(this.configLocationsi.getURL();if (this.hibernateProperties != null) / Add given Hibernate properties to Configuration.config.addProperties(this.hibernateProperties);if (this.dataSource != null) boolean actuallyTransactionAware =(this.useTransactionAwareDataSource | this.dataSource instanceof TransactionAwareDataSourceProxy);/ Set Spring-provided DataSource as Hibernate ConnectionProvider.config.setProperty(Environment.CONNECTION_PROVIDER,actuallyTransactionAware ?TransactionAwareDataSourceConnectionProvider.class.getName() :LocalDataSourceConnectionProvider.class.getName();if (this.jtaTransactionManager != null) / Set Spring-provided JTA TransactionManager as Hibernate property.config.setProperty(Environment.TRANSACTION_MANAGER_STRATEGY, LocalTransactionManagerLookup.class.getName();if (this.mappingLocations != null) / Register given Hibernate mapping definitions, contained in resource files.for (int i = 0; i this.mappingLocations.length; i+) config.addInputStream(this.mappingLocationsi.getInputStream();if (this.cacheableMappingLocations != null) / Register given cacheable Hibernate mapping definitions, read from the file system.for (int i = 0; i this.cacheableMappingLocations.length; i+) config.addCacheableFile(this.cacheableMappingLocationsi.getFile();if (this.mappingJarLocations != null) / Register given Hibernate mapping definitions, contained in jar files.for (int i = 0; i this.mappingJarLocations.length; i+) Resource resource = this.mappingJarLocationsi;config.addJar(resource.getFile();if (this.mappingDirectoryLocations != null) / Register all Hibernate mapping definitions in the given directories.for (int i = 0; i 1) config.setCacheConcurrencyStrategy(className, strategyAndRegion0, strategyAndRegion1);else if (strategyAndRegion.length 0) config.setCacheConcurrencyStrategy(className, strategyAndRegion0);if (this.collectionCacheStrategies != null) / Register cache strategies for mapped collections.for (Enumeration collRoles = this.collectionCacheSpertyNames(); collRoles.hasMoreElements();) String collRole = (String) collRoles.nextElement();String strategyAndRegion =StringUmaDelimitedListToStringArray(this.collectionCacheStrategies.getProperty(collRole);if (strategyAndRegion.length 1) config.setCollectionCacheConcurrencyStrategy(collRole, strategyAndRegion0, strategyAndRegion1);else if (strategyAndRegion.length 0) config.setCollectionCacheConcurrencyStrategy(collRole, strategyAndRegion0);if (this.eventListeners != null) / Register specified Hibernate event listeners.for (Iterator it = this.eventListeners.entrySet().iterator(); it.hasNext();) Map.Entry entry = (Map.Entry) it.next();Assert.isTrue(entry.getKey() instanceof String, Event listener key needs to be of type String);String listenerType = (String) entry.getKey();Object listenerObject = entry.getValue();if (listenerObject instanceof Collection) Collection listeners = (Collection) listenerObject;EventListeners listenerRegistry = config.getEventListeners();Object listenerArray =(Object) Array.newInstance(listenerRegistry.getListenerClassFor(listenerType), listeners.size();listenerArray = listeners.toArray(listenerArray);config.setListeners(listenerType, listenerArray);else config.setListener(listenerType, listenerObject);/ Perform custom post-processing in subclasses.postProcessConfiguration(config);/ 这里是根据Configuration配置创建SessionFactory的地方(Building new Hibernate SessionFactory);this.configuration = config;sf = newSessionFactory(config);/最后把和线程绑定的资源清空finally if (this.dataSource != null) / Reset DataSource holder.configTimeDataSourceHolder.set(null);if (this.jtaTransactionManager != null) / Reset TransactionManager holder.configTimeTransactionManagerHolder.set(null);if (this.lobHandler != null) / Reset LobHandler holder.configTimeLobHandlerHolder.set(null);/ Execute schema update if requested.if (this.schemaUpdate) updateDatabaseSchema();return sf;而直接调用org.hibernate.cfg.Configuration来得到需要的SessionFactory:Java代码 protected SessionFactory newSessionFactory(Configuration config) throws HibernateException return config.buildSessionFactory();所以我们这里看到LocalSessionFactory大致起到的一个读取资源配置然后生成SessionFactory的作用;当然这里在得到 SessionFactory之后,还需要对session的事务管理作一些处理 - 使用了一个Proxy模式对getCurrentSession方法进行了拦截;Java代码 /这里先根据当前的SessionFactory的类型得到Proxy,然后插入Spring定义好的getCurrentSession拦截器protected SessionFactory getTransactionAwareSessionFactoryProxy(SessionFactory target) Class sfInterface = SessionFactory.class;if (target instanceof SessionFactoryImplementor) sfInterface = SessionFactoryImplementor.class;return (SessionFactory) Proxy.newProxyInstance(sfInterface.getClassLoader(),new Class sfInterface, new TransactionAwareInvocationHandler(target);拦截器的实现如下:Java代码 private static class TransactionAwareInvocationHandler implements InvocationHandler private final SessionFactory target;public TransactionAwareInvocationHandler(SessionFactory target) this.target = target;public Object invoke(Object proxy, Method method, Object args) throws Throwable / Invocation on SessionFactory/SessionFactoryImplementor interface coming in./ 这里对getCurrentSession方法进行拦截,得到一个和当前事务绑定的session交给用户if (method.getName().equals(getCurrentSession) / Handle getCurrentSession method: return transactional Session, if any.try return SessionFactoryUtils.doGetSession(SessionFactory) proxy, false);catch (IllegalStateException ex) throw new HibernateException(ex.getMessage();else if (method.getName().equals(equals) / Only consider equal when proxies are identical.return (proxy = args0 ? Boolean.TRUE : Boolean.FALSE);else if (method.getName().equals(hashCode) / Use hashCode of SessionFactory proxy.return new Integer(hashCode();/ 这里是需要运行的SessionFactory的目标方法try return method.invoke(this.target, args);catch (InvocationTargetException ex) throw ex.getTargetException();我们看看getCurrentSession的实现,在SessionFactoryUtils中:Java代码 private static Session doGetSession(SessionFactory sessionFactory, Interceptor entityInterceptor,SQLExceptionTranslator jdbcExceptionTranslator, boolean allowCreate)throws HibernateException, IllegalStateException Assert.notNull(sessionFactory, No SessionFactory specified);/这个TransactionSynchronizationManager的Resource是一个ThreadLocal变量,sessionFactory是一个单例,但ThreadLocal是和线程绑定的/这样就实现了Hiberante中常用的通过ThreadLocal的session管理机制SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);if (sessionHolder != null & !sessionHolder.isEmpty() / pre-bound Hibernate SessionSession session = null;if (TransactionSynchronizationManager.isSynchronizationActive() &sessionHolder.doesNotHoldNonDefaultSession() / Spring transaction management is active -/ register pre-bound Session with it for transactional flushing.session = sessionHolder.getValidatedSession();if (session != null & !sessionHolder.isSynchronizedWithTransaction() logger.debug(Registering Spring transaction synchronization for existing Hibernate Session);TransactionSynchronizationManager.registerSynchronization(new SpringSessionSynchronization(sessionHolder, sessionFactory, jdbcExceptionTranslator, false);sessionHolder.setSynchronizedWithTransaction(true);/ Switch to FlushMode.AUTO, as we have to assume a thread-bound Session/ with FlushMode.NEVER, which needs to allow flushing within the transaction.FlushMode flushMode = session.getFlushMode();if (flushMode.lessThan(FlushMode.COMMIT) &!TransactionSynchronizationManager.isCurrentTransactionReadOnly() session.setFlushMode(FlushMode.AUTO);sessionHolder.setPreviousFlushMode(flushMode);else / No Spring transaction management active - try JTA transaction synchronization.session = getJtaSynchronizedSession(sessionHolder, sessionFactory, jdbcExceptionTranslator);if (session != null) return session;/这里直接打开一个Sessionlogger.debug(Opening Hibernate Session);Session session = (entityInterceptor != null ?sessionFactory.openSession(entityInterceptor) : sessionFactory.openSession();/ Use same Session for further Hibernate actions within the transaction./ Thread object will get removed by synchronization at transaction completion./ 把新打开的Session放到SessionHolder,然后放到ThreadLocal里面去和线程绑定起来,这个ThreadLocal是在 TransactionSynchronizationManager中配置好的,可以根据sessionFactory来索取/ 同时根据事务处理的状态来配置session的属性,比如把FlushMode设置为Never,同时把session和事务处理关联起来if (TransactionSynchronizationManager.isSynchronizationActive() / Were within a Spring-managed transaction, possibly from JtaTransactionManager.logger.debug(Registering Spring transaction synchronization for new Hibernate Session);SessionHolder holderToUse = sessionHolder;if (holderToUse = null) holderToUse = new SessionHolder(session);else holderToUse.addSession(session);if (TransactionSynchronizationManager.isCurrentTransactionReadOnly() session.setFlushMode(FlushMode.NEVER);TransactionSynchronizationManager.registerSynchronization(new SpringSessionSynchronization(holderToUse, sessionFactory, jdbcExceptionTranslator, true);holderToUse.setSynchronizedWithTransaction(true);if (holderToUse != sessionHolder) TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse);else / No Spring transaction management active - try JTA transaction synchronization.registerJtaSynchronization(session, sessionFactory, jdbcExceptionTranslator, sessionHolder);/ Check whether we are allowed to return the Session.if (!allowCreate & !isSessionTransactional(session, sessionFactory) closeSession(session);throw new IllegalStateException(No Hibernate Session bound to thread, +and configuration does not allow creation of non-transactional one here);return session;这里就是在Spring中为使用Hiberante的SessionFactory以及Session做的准备工作,在这个基础上,用户可以通过使用 HibernateTemplate来使用Hibernate的O/R功能,和以前看到的一样这是一个execute的回调:Java代码 public Object execute(HibernateCallback action, boolean exposeNativeSession) throws DataAccessException Assert.notNull(action, Callback object must not be null);/这里得到配置好的Hibernate的SessionSession session = getSession();boolean existingTransaction = SessionFactoryUtils.isSessionTransactional(session, getSessionFactory();if (existingTransaction) logger.debug(Found thread-bound Session for HibernateTemplate);FlushMode previousFlushMode = null;try previousFlushMode = applyFlushMode(session, existingTransaction);enableFilters(session);Session sessionToExpose = (exposeNativeSession ? session : createSessionProxy(session);/这里是回调的入口Object result = action.doInHibernate(sessionToExpose);flushIfNecessary(session, existingTransaction);return result;catch (HibernateException ex) throw convertHibernateAccessException(ex);catch (SQLEx

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论