Spring源代码解析(八):Spring驱动Hibernate的实现

O/R工具出现之后,简化了许多复杂的信息持久化的开发。Spring应用开发者可以通过Spring提供的O/R方案更方便的使用各种持久化工具,比如 Hibernate;下面我们就Spring+Hibernate中的Spring实现做一个简单的剖析。
Spring对 Hinberanate的配置是通过LocalSessionFactoryBean来完成的,这是一个工厂Bean的实现,在基类 AbstractSessionFactoryBean中:

Java代码 复制代码
  1. /**  
  2.  * 这是FactoryBean需要实现的接口方法,直接取得当前的 sessionFactory的值  
  3.  */   
  4. public  Object getObject() {   
  5.      return   this .sessionFactory;   
  6. }  
    /**
     * 这是FactoryBean需要实现的接口方法,直接取得当前的sessionFactory的值
     */
    public Object getObject() {
        return this.sessionFactory;
    }


这个值在afterPropertySet中定义:

Java代码 复制代码
  1. public   void  afterPropertiesSet()  throws  Exception {   
  2.      //这个buildSessionFactory是通过配置信 息得到SessionFactory的地方   
  3.     SessionFactory rawSf = buildSessionFactory();   
  4.      //这里使用了Proxy方法插入对 getCurrentSession的拦截,得到和事务相关的session   
  5.      this .sessionFactory = wrapSessionFactoryIfNecessary(rawSf);   
  6. }  
    public void afterPropertiesSet() throws Exception {
        //这个buildSessionFactory是通过配置信息得到SessionFactory的地方
        SessionFactory rawSf = buildSessionFactory();
        //这里使用了Proxy方法插入对getCurrentSession的拦截,得到和事务相关的session
        this.sessionFactory = wrapSessionFactoryIfNecessary(rawSf);
    }


我们先看看SessionFactory是怎样创建的,这个方法很长,包含了创建Hibernate的SessionFactory的详尽步骤:

Java代码 复制代码
  1. protected  SessionFactory buildSessionFactory()  throws  Exception {   
  2.     SessionFactory sf =  null ;   
  3.   
  4.      // Create Configuration instance.   
  5.     Configuration config = newConfiguration();   
  6.   
  7.      //这里配置数据源,事务管理器,LobHander到 Holder中,这个Holder是一个ThreadLocal变量,这样这些资源就和线程绑定了   
  8.      if  ( this .dataSource !=  null ) {   
  9.          // Make given DataSource available for SessionFactory configuration.   
  10.         configTimeDataSourceHolder.set( this .dataSource);   
  11.     }   
  12.   
  13.      if  ( this .jtaTransactionManager !=  null ) {   
  14.          // Make Spring-provided JTA TransactionManager available.   
  15.         configTimeTransactionManagerHolder.set( this .jtaTransactionManager);   
  16.     }   
  17.   
  18.      if  ( this .lobHandler !=  null ) {   
  19.          // Make given LobHandler available for SessionFactory configuration.   
  20.          // Do early because because mapping resource might refer to custom types.   
  21.         configTimeLobHandlerHolder.set( this .lobHandler);   
  22.     }   
  23.   
  24.      //这里是使用Hibernate的各个属性的配置,这里使用 了Configuration类来抽象这些数据   
  25.      try  {   
  26.          // Set connection release mode "on_close" as default.   
  27.          // This was the case for Hibernate 3.0; Hibernate 3.1 changed   
  28.          // it to "auto" (i.e. "after_statement" or "after_transaction").   
  29.          // However, for Spring's resource management (in particular for   
  30.          // HibernateTransactionManager), "on_close" is the better default.   
  31.         config.setProperty(Environment.RELEASE_CONNECTIONS, ConnectionReleaseMode.ON_CLOSE.toString());   
  32.   
  33.          if  (!isExposeTransactionAwareSessionFactory()) {   
  34.              // Not exposing a SessionFactory proxy with transaction-aware   
  35.              // getCurrentSession() method -> set Hibernate 3.1 CurrentSessionContext   
  36.              // implementation instead, providing the Spring-managed Session that way.   
  37.              // Can be overridden by a custom value for corresponding Hibernate property.   
  38.             config.setProperty(Environment.CURRENT_SESSION_CONTEXT_CLASS,   
  39.                      "org.springframework.orm.hibernate3.SpringSessionContext" );   
  40.         }   
  41.   
  42.          if  ( this .entityInterceptor !=  null ) {   
  43.              // Set given entity interceptor at SessionFactory level.   
  44.             config.setInterceptor( this .entityInterceptor);   
  45.         }   
  46.   
  47.          if  ( this .namingStrategy !=  null ) {   
  48.              // Pass given naming strategy to Hibernate Configuration.   
  49.             config.setNamingStrategy( this .namingStrategy);   
  50.         }   
  51.   
  52.          if  ( this .typeDefinitions !=  null ) {   
  53.              // Register specified Hibernate type definitions.   
  54.             Mappings mappings = config.createMappings();   
  55.              for  ( int  i =  0 ; i <  this .typeDefinitions.length; i++) {   
  56.                 TypeDefinitionBean typeDef =  this .typeDefinitions[i];   
  57.                 mappings.addTypeDef(typeDef.getTypeName(), typeDef.getTypeClass(), typeDef.getParameters());   
  58.             }   
  59.         }   
  60.   
  61.          if  ( this .filterDefinitions !=  null ) {   
  62.              // Register specified Hibernate FilterDefinitions.   
  63.              for  ( int  i =  0 ; i <  this .filterDefinitions.length; i++) {   
  64.                 config.addFilterDefinition( this .filterDefinitions[i]);   
  65.             }   
  66.         }   
  67.   
  68.          if  ( this .configLocations !=  null ) {   
  69.              for  ( int  i =  0 ; i <  this .configLocations.length; i++) {   
  70.                  // Load Hibernate configuration from given location.   
  71.                 config.configure( this .configLocations[i].getURL());   
  72.             }   
  73.         }   
  74.   
  75.          if  ( this .hibernateProperties !=  null ) {   
  76.              // Add given Hibernate properties to Configuration.   
  77.             config.addProperties( this .hibernateProperties);   
  78.         }   
  79.   
  80.          if  ( this .dataSource !=  null ) {   
  81.              boolean  actuallyTransactionAware =   
  82.                     ( this .useTransactionAwareDataSource ||  this .dataSource  instanceof  TransactionAwareDataSourceProxy);   
  83.              // Set Spring-provided DataSource as Hibernate ConnectionProvider.   
  84.             config.setProperty(Environment.CONNECTION_PROVIDER,   
  85.                     actuallyTransactionAware ?   
  86.                     TransactionAwareDataSourceConnectionProvider. class .getName() :   
  87.                     LocalDataSourceConnectionProvider. class .getName());   
  88.         }   
  89.   
  90.          if  ( this .jtaTransactionManager !=  null ) {   
  91.              // Set Spring-provided JTA TransactionManager as Hibernate property.   
  92.             config.setProperty(   
  93.                     Environment.TRANSACTION_MANAGER_STRATEGY, LocalTransactionManagerLookup. class .getName());   
  94.         }   
  95.   
  96.          if  ( this .mappingLocations !=  null ) {   
  97.              // Register given Hibernate mapping definitions, contained in resource files.   
  98.              for  ( int  i =  0 ; i <  this .mappingLocations.length; i++) {   
  99.                 config.addInputStream( this .mappingLocations[i].getInputStream());   
  100.             }   
  101.         }   
  102.   
  103.          if  ( this .cacheableMappingLocations !=  null ) {   
  104.              // Register given cacheable Hibernate mapping definitions, read from the file system.   
  105.              for  ( int  i =  0 ; i <  this .cacheableMappingLocations.length; i++) {   
  106.                 config.addCacheableFile( this .cacheableMappingLocations[i].getFile());   
  107.             }   
  108.         }   
  109.   
  110.          if  ( this .mappingJarLocations !=  null ) {   
  111.              // Register given Hibernate mapping definitions, contained in jar files.   
  112.              for  ( int  i =  0 ; i <  this .mappingJarLocations.length; i++) {   
  113.                 Resource resource =  this .mappingJarLocations[i];   
  114.                 config.addJar(resource.getFile());   
  115.             }   
  116.         }   
  117.   
  118.          if  ( this .mappingDirectoryLocations !=  null ) {   
  119.              // Register all Hibernate mapping definitions in the given directories.   
  120.              for  ( int  i =  0 ; i <  this .mappingDirectoryLocations.length; i++) {   
  121.                 File file =  this .mappingDirectoryLocations[i].getFile();   
  122.                  if  (!file.isDirectory()) {   
  123.                      throw   new  IllegalArgumentException(   
  124.                              "Mapping directory location ["  +  this .mappingDirectoryLocations[i] +   
  125.                              "] does not denote a directory" );   
  126.                 }   
  127.                 config.addDirectory(file);   
  128.             }   
  129.         }   
  130.   
  131.          if  ( this .entityCacheStrategies !=  null ) {   
  132.              // Register cache strategies for mapped entities.   
  133.              for  (Enumeration classNames =  this .entityCacheStrategies.propertyNames(); classNames.hasMoreElements();) {   
  134.                 String className = (String) classNames.nextElement();   
  135.                 String[] strategyAndRegion =   
  136.                         StringUtils.commaDelimitedListToStringArray( this .entityCacheStrategies.getProperty(className));   
  137.                  if  (strategyAndRegion.length >  1 ) {   
  138.                     config.setCacheConcurrencyStrategy(className, strategyAndRegion[ 0 ], strategyAndRegion[ 1 ]);   
  139.                 }   
  140.                  else   if  (strategyAndRegion.length >  0 ) {   
  141.                     config.setCacheConcurrencyStrategy(className, strategyAndRegion[ 0 ]);   
  142.                 }   
  143.             }   
  144.         }   
  145.   
  146.          if  ( this .collectionCacheStrategies !=  null ) {   
  147.              // Register cache strategies for mapped collections.   
  148.              for  (Enumeration collRoles =  this .collectionCacheStrategies.propertyNames(); collRoles.hasMoreElements();) {   
  149.                 String collRole = (String) collRoles.nextElement();   
  150.                 String[] strategyAndRegion =   
  151.                         StringUtils.commaDelimitedListToStringArray( this .collectionCacheStrategies.getProperty(collRole));   
  152.                  if  (strategyAndRegion.length >  1 ) {   
  153.                     config.setCollectionCacheConcurrencyStrategy(collRole, strategyAndRegion[ 0 ], strategyAndRegion[ 1 ]);   
  154.                 }   
  155.                  else   if  (strategyAndRegion.length >  0 ) {   
  156.                     config.setCollectionCacheConcurrencyStrategy(collRole, strategyAndRegion[ 0 ]);   
  157.                 }   
  158.             }   
  159.         }   
  160.   
  161.          if  ( this .eventListeners !=  null ) {   
  162.              // Register specified Hibernate event listeners.   
  163.              for  (Iterator it =  this .eventListeners.entrySet().iterator(); it.hasNext();) {   
  164.                 Map.Entry entry = (Map.Entry) it.next();   
  165.                 Assert.isTrue(entry.getKey()  instanceof  String,  "Event listener key needs to be of type String" );   
  166.                 String listenerType = (String) entry.getKey();   
  167.                 Object listenerObject = entry.getValue();   
  168.                  if  (listenerObject  instanceof  Collection) {   
  169.                     Collection listeners = (Collection) listenerObject;   
  170.                     EventListeners listenerRegistry = config.getEventListeners();   
  171.                     Object[] listenerArray =   
  172.                             (Object[]) Array.newInstance(listenerRegistry.getListenerClassFor(listenerType), listeners.size());   
  173.                     listenerArray = listeners.toArray(listenerArray);   
  174.                     config.setListeners(listenerType, listenerArray);   
  175.                 }   
  176.                  else  {   
  177.                     config.setListener(listenerType, listenerObject);   
  178.                 }   
  179.             }   
  180.         }   
  181.   
  182.          // Perform custom post-processing in subclasses.   
  183.         postProcessConfiguration(config);   
  184.   
  185.          // 这里是根据Configuration配置创建 SessionFactory的地方   
  186.         logger.info( "Building new Hibernate SessionFactory" );   
  187.          this .configuration = config;   
  188.         sf = newSessionFactory(config);   
  189.     }   
  190.      //最后把和线程绑定的资源清空   
  191.      finally  {   
  192.          if  ( this .dataSource !=  null ) {   
  193.              // Reset DataSource holder.   
  194.             configTimeDataSourceHolder.set( null );   
  195.         }   
  196.   
  197.          if  ( this .jtaTransactionManager !=  null ) {   
  198.              // Reset TransactionManager holder.   
  199.             configTimeTransactionManagerHolder.set( null );   
  200.         }   
  201.   
  202.          if  ( this .lobHandler !=  null ) {   
  203.              // Reset LobHandler holder.   
  204.             configTimeLobHandlerHolder.set( null );   
  205.         }   
  206.     }   
  207.   
  208.      // Execute schema update if requested.   
  209.      if  ( this .schemaUpdate) {   
  210.         updateDatabaseSchema();   
  211.     }   
  212.   
  213.      return  sf;   
  214. }  
    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 Spring's 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.typeDefinitions[i];
                    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.filterDefinitions[i]);
                }
            }

            if (this.configLocations != null) {
                for (int i = 0; i < this.configLocations.length; i++) {
                    // Load Hibernate configuration from given location.
                    config.configure(this.configLocations[i].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.mappingLocations[i].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.cacheableMappingLocations[i].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.mappingJarLocations[i];
                    config.addJar(resource.getFile());
                }
            }

            if (this.mappingDirectoryLocations != null) {
                // Register all Hibernate mapping definitions in the given directories.
                for (int i = 0; i < this.mappingDirectoryLocations.length; i++) {
                    File file = this.mappingDirectoryLocations[i].getFile();
                    if (!file.isDirectory()) {
                        throw new IllegalArgumentException(
                                "Mapping directory location [" + this.mappingDirectoryLocations[i] +
                                "] does not denote a directory");
                    }
                    config.addDirectory(file);
                }
            }

            if (this.entityCacheStrategies != null) {
                // Register cache strategies for mapped entities.
                for (Enumeration classNames = this.entityCacheStrategies.propertyNames(); classNames.hasMoreElements();) {
                    String className = (String) classNames.nextElement();
                    String[] strategyAndRegion =
                            StringUtils.commaDelimitedListToStringArray(this.entityCacheStrategies.getProperty(className));
                    if (strategyAndRegion.length > 1) {
                        config.setCacheConcurrencyStrategy(className, strategyAndRegion[0], strategyAndRegion[1]);
                    }
                    else if (strategyAndRegion.length > 0) {
                        config.setCacheConcurrencyStrategy(className, strategyAndRegion[0]);
                    }
                }
            }

            if (this.collectionCacheStrategies != null) {
                // Register cache strategies for mapped collections.
                for (Enumeration collRoles = this.collectionCacheStrategies.propertyNames(); collRoles.hasMoreElements();) {
                    String collRole = (String) collRoles.nextElement();
                    String[] strategyAndRegion =
                            StringUtils.commaDelimitedListToStringArray(this.collectionCacheStrategies.getProperty(collRole));
                    if (strategyAndRegion.length > 1) {
                        config.setCollectionCacheConcurrencyStrategy(collRole, strategyAndRegion[0], strategyAndRegion[1]);
                    }
                    else if (strategyAndRegion.length > 0) {
                        config.setCollectionCacheConcurrencyStrategy(collRole, strategyAndRegion[0]);
                    }
                }
            }

            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的地方
            logger.info("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代码 复制代码
  1. protected  SessionFactory newSessionFactory(Configuration config)  throws  HibernateException {   
  2.      return  config.buildSessionFactory();   
  3. }  
    protected SessionFactory newSessionFactory(Configuration config) throws HibernateException {
        return config.buildSessionFactory();
    }


所以我们这里看到LocalSessionFactory大致起到的一个读取资源配置然后生成SessionFactory的作用;当然这里在得 到 SessionFactory之后,还需要对session的事务管理作一些处理 - 使用了一个Proxy模式对getCurrentSession方法进行了拦截;

Java代码 复制代码
  1. //这里先根据当前的SessionFactory的类型得到Proxy,然后插入 Spring定义好的getCurrentSession拦截器   
  2.      protected  SessionFactory getTransactionAwareSessionFactoryProxy(SessionFactory target) {   
  3.         Class sfInterface = SessionFactory. class ;   
  4.          if  (target  instanceof  SessionFactoryImplementor) {   
  5.             sfInterface = SessionFactoryImplementor. class ;   
  6.         }   
  7.          return  (SessionFactory) Proxy.newProxyInstance(sfInterface.getClassLoader(),   
  8.                  new  Class[] {sfInterface},  new  TransactionAwareInvocationHandler(target));   
  9.     }  
//这里先根据当前的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代码 复制代码
  1. private   static   class  TransactionAwareInvocationHandler  implements  InvocationHandler {   
  2.   
  3.      private   final  SessionFactory target;   
  4.   
  5.      public  TransactionAwareInvocationHandler(SessionFactory target) {   
  6.          this .target = target;   
  7.     }   
  8.   
  9.      public  Object invoke(Object proxy, Method method, Object[] args)  throws  Throwable {   
  10.          // Invocation on SessionFactory/SessionFactoryImplementor interface coming in...   
  11.          // 这里对getCurrentSession方法 进行拦截,得到一个和当前事务绑定的session交给用户   
  12.          if  (method.getName().equals( "getCurrentSession" )) {   
  13.              // Handle getCurrentSession method: return transactional Session, if any.   
  14.              try  {   
  15.                  return  SessionFactoryUtils.doGetSession((SessionFactory) proxy,  false );   
  16.             }   
  17.              catch  (IllegalStateException ex) {   
  18.                  throw   new  HibernateException(ex.getMessage());   
  19.             }   
  20.         }   
  21.          else   if  (method.getName().equals( "equals" )) {   
  22.              // Only consider equal when proxies are identical.   
  23.              return  (proxy == args[ 0 ] ? Boolean.TRUE : Boolean.FALSE);   
  24.         }   
  25.          else   if  (method.getName().equals( "hashCode" )) {   
  26.              // Use hashCode of SessionFactory proxy.   
  27.              return   new  Integer(hashCode());   
  28.         }   
  29.   
  30.          // 这里是需要运行的SessionFactory 的目标方法   
  31.          try  {   
  32.              return  method.invoke( this .target, args);   
  33.         }   
  34.          catch  (InvocationTargetException ex) {   
  35.              throw  ex.getTargetException();   
  36.         }   
  37.     }   
  38. }  
    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 == args[0] ? 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代码 复制代码
  1. private   static  Session doGetSession(   
  2.             SessionFactory sessionFactory, Interceptor entityInterceptor,   
  3.             SQLExceptionTranslator jdbcExceptionTranslator,  boolean  allowCreate)   
  4.              throws  HibernateException, IllegalStateException {   
  5.   
  6.         Assert.notNull(sessionFactory,  "No SessionFactory specified" );   
  7.   
  8.          //这个 TransactionSynchronizationManager的Resource是一个ThreadLocal变 量,sessionFactory是一个单例,但ThreadLocal是和线程绑定的   
  9.          //这样就实现了Hiberante中常用的通过 ThreadLocal的session管理机制   
  10.         SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);   
  11.          if  (sessionHolder !=  null  && !sessionHolder.isEmpty()) {   
  12.              // pre-bound Hibernate Session   
  13.             Session session =  null ;   
  14.              if  (TransactionSynchronizationManager.isSynchronizationActive() &&   
  15.                     sessionHolder.doesNotHoldNonDefaultSession()) {   
  16.                  // Spring transaction management is active ->   
  17.                  // register pre-bound Session with it for transactional flushing.   
  18.                 session = sessionHolder.getValidatedSession();   
  19.                  if  (session !=  null  && !sessionHolder.isSynchronizedWithTransaction()) {   
  20.                     logger.debug( "Registering Spring transaction synchronization for existing Hibernate Session" );   
  21.                     TransactionSynchronizationManager.registerSynchronization(   
  22.                              new  SpringSessionSynchronization(sessionHolder, sessionFactory, jdbcExceptionTranslator,  false ));   
  23.                     sessionHolder.setSynchronizedWithTransaction( true );   
  24.                      // Switch to FlushMode.AUTO, as we have to assume a thread-bound Session   
  25.                      // with FlushMode.NEVER, which needs to allow flushing within the transaction.   
  26.                     FlushMode flushMode = session.getFlushMode();   
  27.                      if  (flushMode.lessThan(FlushMode.COMMIT) &&   
  28.                             !TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {   
  29.                         session.setFlushMode(FlushMode.AUTO);   
  30.                         sessionHolder.setPreviousFlushMode(flushMode);   
  31.                     }   
  32.                 }   
  33.             }   
  34.              else  {   
  35.                  // No Spring transaction management active -> try JTA transaction synchronization.   
  36.                 session = getJtaSynchronizedSession(sessionHolder, sessionFactory, jdbcExceptionTranslator);   
  37.             }   
  38.              if  (session !=  null ) {   
  39.                  return  session;   
  40.             }   
  41.         }   
  42.          //这里直接打开一个Session   
  43.         logger.debug( "Opening Hibernate Session" );   
  44.         Session session = (entityInterceptor !=  null  ?   
  45.                 sessionFactory.openSession(entityInterceptor) : sessionFactory.openSession());   
  46.   
  47.          // Use same Session for further Hibernate actions within the transaction.   
  48.          // Thread object will get removed by synchronization at transaction completion.   
  49.          // 把新打开的Session放到 SessionHolder,然后放到ThreadLocal里面去和线程绑定起来,这个ThreadLocal是 在 TransactionSynchronizationManager中配置好的,可以根据sessionFactory来索取   
  50.          // 同时根据事务处理的状态来配置session的 属性,比如把FlushMode设置为Never,同时把session和事务处理关联起来   
  51.          if  (TransactionSynchronizationManager.isSynchronizationActive()) {   
  52.              // We're within a Spring-managed transaction, possibly from JtaTransactionManager.   
  53.             logger.debug( "Registering Spring transaction synchronization for new Hibernate Session" );   
  54.             SessionHolder holderToUse = sessionHolder;   
  55.              if  (holderToUse ==  null ) {   
  56.                 holderToUse =  new  SessionHolder(session);   
  57.             }   
  58.              else  {   
  59.                 holderToUse.addSession(session);   
  60.             }   
  61.              if  (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {   
  62.                 session.setFlushMode(FlushMode.NEVER);   
  63.             }   
  64.             TransactionSynchronizationManager.registerSynchronization(   
  65.                      new  SpringSessionSynchronization(holderToUse, sessionFactory, jdbcExceptionTranslator,  true ));   
  66.             holderToUse.setSynchronizedWithTransaction( true );   
  67.              if  (holderToUse != se
Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值