kapok

          垃圾桶,嘿嘿,我藏的這么深你們還能找到啊,真牛!

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            455 隨筆 :: 0 文章 :: 76 評(píng)論 :: 0 Trackbacks
          http://dev.csdn.net/article/64/64424.shtm


          Spring的輕量級(jí)的bean容器為業(yè)務(wù)對(duì)象(business objects)、DAO對(duì)象和資源(如:JDBC數(shù)據(jù)源或者Hibernate SessionFactorie等)對(duì)象提供了IoC類型的裝配能力。Spring使用一個(gè)xml格式的應(yīng)用配置文件為開發(fā)者提供了一種通過解析定制的屬性文件來手動(dòng)管理單實(shí)例對(duì)象或者工廠對(duì)象的選擇性。由于Spring將非入侵性做為一個(gè)重要的目標(biāo),因此可以由Spring配置管理的bean對(duì)象均不需要依賴Spring自有的接口和類就可以通過它們的bean屬性完成配置。這個(gè)概念可以被應(yīng)用到任何環(huán)境中,無論你開發(fā)的是一個(gè)J2EE的web應(yīng)用還是一個(gè)桌面應(yīng)用甚至只是一個(gè)applet都可以。

              在使用Hibernate的應(yīng)用中, Spring的對(duì)DAO對(duì)象通常的事務(wù)管理特別應(yīng)該引起關(guān)注。它的目的就是分離數(shù)據(jù)訪問和事務(wù)處理,使事務(wù)性業(yè)務(wù)對(duì)象不與任何特殊的數(shù)據(jù)訪問或者事務(wù)策略綁在一起,從而不影響業(yè)務(wù)對(duì)象的可復(fù)用性。這種劃分既可以經(jīng)由事務(wù)模板(TransactionTemplate)用編程的方式實(shí)現(xiàn),也可以經(jīng)由面向方面(AOP)事務(wù)攔截器(TransactionTemplate)用聲明的方式實(shí)現(xiàn)。無論是本地的Hibernate / JDBC事務(wù),還是JTA事務(wù)都支持對(duì)象外的事務(wù)策略,這對(duì)于本地的無狀態(tài)會(huì)話Bean(Stateless Session Beans)是一個(gè)非常有用的選擇。

              Spring的HibernateTemplate類提供了一個(gè)簡(jiǎn)單的方式實(shí)現(xiàn)了Hibernate-based DAO對(duì)象而不必關(guān)心如何獲得Hibernate的Session實(shí)例,也不必關(guān)心多方參與的事務(wù)處理。無需使用try-catch塊,也無需進(jìn)行事務(wù)檢查。一個(gè)簡(jiǎn)單的Hibernate訪問方法就完全解決了些麻煩! 無論是在多個(gè)DAO接口還是在多方事務(wù)的情況下,Spring使得多種DAO對(duì)象無縫地協(xié)同工作。例如:某些DAO對(duì)象可能是基于plain JDBC的實(shí)現(xiàn),更適合于經(jīng)由Spring的JdbcTemplate來避免手動(dòng)的異常處理。

                你可以單獨(dú)地使用許多Spring特性,因?yàn)镾pring的所有對(duì)象都是設(shè)計(jì)成可復(fù)用的JavaBean對(duì)象的集合。也不要因?yàn)镾pring可以提供一個(gè)完整的應(yīng)該框架而氣餒!使用其他的Spring特性時(shí),應(yīng)用配置概念是一個(gè)附加的特性,并不是一個(gè)必須的特性。無論如何,當(dāng)你要決定去構(gòu)建一個(gè)象Spring這樣的內(nèi)在的基礎(chǔ)架構(gòu)的時(shí)候,在使用Spring的路途上沒有什么范圍上的限制。

           

          1. 介紹: 資源管理

                 典型的業(yè)務(wù)應(yīng)用系統(tǒng)常常由于重復(fù)的資源管理代碼而導(dǎo)致混亂。許多項(xiàng)目試著用自己的方法來解決這個(gè)問題,有時(shí)要為此付出失敗的代價(jià),Spring針對(duì)適當(dāng)?shù)馁Y源管理提倡了一種引人注目的簡(jiǎn)單方法:即經(jīng)由模板來倒置控制(Inversion of control),例如:基礎(chǔ)類使用回調(diào)接口,或者應(yīng)用AOP攔截器。其基礎(chǔ)核心是適當(dāng)?shù)馁Y源處理和將特殊的API異常轉(zhuǎn)換為一個(gè)unchecked的基礎(chǔ)異常。

                 Spring引入了一個(gè)DAO異常層適用于任何數(shù)據(jù)訪問策略。對(duì)于直接的JDBC,JdbcTemplate類關(guān)注于連接處理,并且關(guān)注于對(duì)SQLException轉(zhuǎn)換為適當(dāng)?shù)腄ataAccessException,包括對(duì)特殊的數(shù)據(jù)庫SQL錯(cuò)誤轉(zhuǎn)換為有意義的異常。 經(jīng)由不同的事務(wù)管理對(duì)象,Spring支持JTA和JDBC事務(wù)。Spring 也提供對(duì)Hibernate和JDO的支持,它的這種支持由與JdbcTemplate類的作用相類似的HibernateTemplate類和JdoTemplate類, 以及HibernateInterceptor類、JdoInterceptor類,還有Hibernate、JDO 事務(wù)管理類組成。

                 最主要的目的是要使應(yīng)用的層次分明,為此將數(shù)據(jù)訪問和事務(wù)處理同應(yīng)用對(duì)象分離開來。所有的業(yè)務(wù)對(duì)象都不再依賴數(shù)據(jù)訪問或者事務(wù)策略。不再有硬編碼的資源查找代碼,不再有難以替換的單例對(duì)象,也不再需要定制服務(wù)注冊(cè)。

                所有的單獨(dú)的數(shù)據(jù)訪問特性均無需依賴于Spring,可以單獨(dú)使用,無需讓Spring知道,同時(shí)也可以通過Spring的應(yīng)用配置(提供基于XML的配置和對(duì)普通JavaBean實(shí)例的交叉引用)來進(jìn)行裝配。在一個(gè)典型的Spring應(yīng)用中,大部分重要的對(duì)象都是普通的JavaBean:數(shù)據(jù)訪問模板對(duì)象(data access templates)、數(shù)據(jù)訪問對(duì)象(使用數(shù)據(jù)訪問模板對(duì)象的對(duì)象)、事務(wù)管理對(duì)象及業(yè)務(wù)對(duì)象(使用數(shù)據(jù)訪問對(duì)象和事務(wù)對(duì)象的對(duì)象),web表示分解對(duì)象、web控制對(duì)象(使用業(yè)務(wù)對(duì)象的對(duì)象)等等。

          2. 應(yīng)用配置中的資源定義

              為了避免應(yīng)用對(duì)象將資源查找的代碼硬編碼,Spring允許在應(yīng)用配置中將一個(gè)如JDBC DataSource或者Hibernate SessionFactory定義為一個(gè)Bean。應(yīng)用對(duì)象如果需要訪問資源只需要通過Bean引用(DAO定義在下一部分說明)接受先前定義的實(shí)例的引用。以下的內(nèi)容引用自一個(gè)應(yīng)用配置定義,顯示了如何建立一個(gè)JDBC DataSource和一個(gè)Hibernate的SessionFactory:

           <beans>

          <bean id="myDataSource" class="org.springframework.jndi

          .JndiObjectFactoryBean">
          <property name="jndiName">
          <value>jdbc/myds</value>
          </property>
          </bean>

          <bean id="mySessionFactory" class="org.springframework.orm.hibernate

          .LocalSessionFactoryBean">
          <property name="mappingResources">
          <list>
          <value>product.hbm.xml</value>
          </list>
          </property>
          <property name="hibernateProperties">
          <props>
          <prop key="hibernate.dialect">net.sf.hibernate.dialect

          .MySQLDialect</prop>
          </props>
          </property>
          <property name="dataSource">
          <ref bean="myDataSource"/>
          </property>
          </bean>

          ...

          </beans>

                注意選擇是用JNDI來定位數(shù)據(jù)源還是從一個(gè)象Jakarta Commons DBCP BasicDataSource這樣的本地定義取得一個(gè)數(shù)據(jù)源,只是一個(gè)改變配置的事:

          <bean id="myDataSource"
                class="org.apache.commons

          .dbcp.BasicDataSource" destroy-method="close">
          <property name="driverClassName">
          <value>org.hsqldb.jdbcDriver</value>
          </property>
          <property name="url">
          <value>jdbc:hsqldb:hsql://localhost:9001</value>
          </property>
          <property name="username">
          <value>sa</value>
          </property>
          <property name="password">
          <value></value>
          </property>
          </bean>

                 你也可以使用一個(gè)JNDI查找SessionFactory,但是通常對(duì)于EJB環(huán)境之外的應(yīng)用來說并不是需要的(參考"container resources vs local resources"部分的討論)。

          3. 倒置控制(Inversion of Control): 模板和回調(diào)

              模板的基本編程模式就象你將在下面看到那樣,至于方法就如同任何定制的數(shù)據(jù)訪問對(duì)象或者業(yè)務(wù)的對(duì)象的方法一樣。除了需要向其提供一個(gè)Hibernate的SessionFactory之外,再?zèng)]有對(duì)周圍執(zhí)行對(duì)象的信賴的限制。雖然最好是從一個(gè)Spring的應(yīng)用配置中經(jīng)由一個(gè)簡(jiǎn)單setSessionFactory bean的屬性設(shè)置使用Bean引用來獲得它,但隨后你可以從任何地方獲得它。隨后的引用片段包括一段在Spring應(yīng)用配置中對(duì)DAO定義的配置,其中引用了在其前面定義的SessionFactory,和一段DAO方法的實(shí)現(xiàn)的例子。

          <beans>
          
          <bean id="myProductDao" class="product.ProductDaoImpl">
          <property name="sessionFactory">
          <ref bean="mySessionFactory"/>
          </property>
          </bean>
          
          ...
          
          </beans>

          public class ProductDaoImpl implements ProductDao {
          
          private SessionFactory sessionFactory;
          
          public void setSessionFactory(SessionFactory 
             sessionFactory) {
          this.sessionFactory = sessionFactory;
          }
          
          public List loadProductsByCategory(final String 
            category) {
          HibernateTemplate hibernateTemplate =
          new HibernateTemplate(this.sessionFactory);
          
          return (List) hibernateTemplate.execute(
          new HibernateCallback() {
          public Object doInHibernate(Session session) throws
           HibernateException {
          List result = session.find(
          "from test.Product product where product.category=?",
          category, Hibernate.STRING);
          // do some further stuff with the result list
          return result;
          }
          }
          );
          }
          }

                 一個(gè)回調(diào)的實(shí)現(xiàn)可以被有效地用在任何Hibernate數(shù)據(jù)訪問中。在任何情況下都由HibernateTemplate來管理Session的開閉和自動(dòng)的多方事務(wù)。模板實(shí)例是線程安全和可重用的,因此它們可以做為其他類的變量。


                 對(duì)于簡(jiǎn)單的單步的動(dòng)作,象find, load, saveOrUpdate或者delete的調(diào)用,HibernateTemplate提供更為便利的選擇以代替象一行的回調(diào)的執(zhí)行。此外,Spring提供了一個(gè)方便的基本類,就是HibernateDaoSupport類,它提供了setSessionFactory方法來接受一個(gè)SessionFactory,同時(shí)提供了getSessionFactory和getHibernateTemplate方法供其繼承類使用。將這些結(jié)合起來,允許對(duì)于典型的需求給出了非常簡(jiǎn)單的DAO實(shí)現(xiàn):

          public class ProductDaoImpl extends HibernateDaoSupport implements
           ProductDao {
          
          public List loadProductsByCategory(String category) {
          return getHibernateTemplate().find(
          "from test.Product product where product.category=?", category,
          Hibernate.STRING);
          }
          }

           

          4. 應(yīng)用一個(gè)AOP攔截器代替一個(gè)模板

             除使用HibernateTemplate之外的另一個(gè)選擇就是使用Spring的AOP HibernateInterceptor。用直接在一個(gè)委托的try/catch塊中編寫Hibernate代碼,配合相應(yīng)的在應(yīng)用配置中分別的攔截器配置來代替執(zhí)行回調(diào)。下面的片段顯示了一個(gè)Spring應(yīng)用配置中的DAO, interceptor和proxy的各自的定義,同時(shí)給出了一個(gè)DAO方法實(shí)現(xiàn)的例子:

          <beans>
          
          ...
          
          <bean id="myHibernateInterceptor"
                class="org.springframework.orm.hibernate
          .HibernateInterceptor">
          <property name="sessionFactory">
          <ref bean="mySessionFactory"/>
          </property>
          </bean>
          
          <bean id="myProductDaoTarget" class="product.ProductDaoImpl">
          <property name="sessionFactory">
          <ref bean="mySessionFactory"/>
          </property>
          </bean>
          
          <bean id="myProductDao" class="org.springframework.aop
          .framework.ProxyFactoryBean">
          <property name="proxyInterfaces">
          <value>product.ProductDao</value>
          </property>
          <property name="interceptorNames">
          <list>
          <value>myHibernateInterceptor</value>
          <value>myProductDaoTarget</value>
          </list>
          </property>
          </bean>
          
          ...
          
          </beans>

           
          public class ProductDaoImpl extends HibernateDaoSupport 
             implements ProductDao {
          
          public List loadProductsByCategory(final String category)
           throws MyException {
          Session session = SessionFactoryUtils
          .getSession(getSessionFactory(), false);
          try {
          List result = session.find(
          "from test.Product product where product.category=?",
          category, Hibernate.STRING);
          if (result == null) {
          throw new MyException("invalid search result");
          }
          return result;
          }
          catch (HibernateException ex) {
          throw SessionFactoryUtils.convertHibernateAccessException(ex);
          }
          }
          }
          

                  這個(gè)方法將只在有一個(gè)與它配合的HibernateInterceptor時(shí)才能正常工作,HibernateInterceptor為它負(fù)責(zé)在方法調(diào)用前線程綁定Session的開啟和方法調(diào)用后的關(guān)閉。getSession方法調(diào)用中的"false"標(biāo)志是要確認(rèn)Session必須是已經(jīng)存在的,如果沒有發(fā)現(xiàn)任何一個(gè)Session,SessionFactoryUtils將會(huì)為其創(chuàng)建一個(gè)。如果已經(jīng)有一個(gè)Session句柄綁定在本線程上,比如是由一個(gè)HibernateTransactionManager事務(wù)綁定的,在任何情況下SessionFactoryUtils會(huì)自動(dòng)接入這個(gè)Session。HibernateTemplate在底層也使用SessionFactoryUtils,與以上說的方式基本是一樣的。

                 HibernateInterceptor的主要益處是它允許在數(shù)據(jù)訪問代碼中拋出checked application exception,而HibernateTemplate由于受限于回調(diào)只能在其中拋出unchecked exceptions。注意到這點(diǎn)我們可以推遲各自的檢驗(yàn),同時(shí)在回調(diào)后拋出應(yīng)用異常。攔截方式的主要缺點(diǎn)是它需要在配置中進(jìn)行特殊的配置。HibernateTemplate在大多數(shù)情況下都是一種簡(jiǎn)單好用的方法。

          5. 程序事務(wù)劃分

             在這種底層的數(shù)據(jù)訪問服務(wù)之上,事務(wù)處理可以在更高的應(yīng)用層被劃分 ,形成一些操作。這里除了需要一個(gè)Spring的PlatformTransactionManager對(duì)象外,對(duì)于周圍運(yùn)行的業(yè)務(wù)對(duì)象也沒有任何限制。同樣的,其后你可以從任何地方獲得它們,但是經(jīng)由Bean引用的方式通過setTransactionManage方法獲得更為適合,象productDAO要經(jīng)由一個(gè)setProductDao方法獲得一樣。下面的引用片段顯示了在一個(gè)Spring應(yīng)用配置中的事務(wù)管理對(duì)象和業(yè)務(wù)對(duì)象的定義,并且還提供了一個(gè)業(yè)務(wù)方法實(shí)現(xiàn)的例子:

          <beans>
          
          ...
          
          <bean id="myTransactionManager"
                class="org.springframework.orm.hibernate
          .HibernateTransactionManager">
          <property name="sessionFactory">
          <ref bean="mySessionFactory"/>
          </property>
          </bean>
          
          <bean id="myProductService" class="product.ProductServiceImpl">
          <property name="transactionManager">
          <ref bean="myTransactionManager"/>
          </property>
          <property name="productDao">
          <ref bean="myProductDao"/>
          </property>
          </bean>
          
          </beans>

           
          public class ProductServiceImpl implements ProductService {
          
          private PlatformTransactionManager transactionManager;
          private ProductDao productDao;
          
          public void setTransactionManager(PlatformTransactionManager 
            transactionManager) {
          this.transactionManager = transactionManager;
          }
          
          public void setProductDao(ProductDao productDao) {
          this.productDao = productDao;
          }
          
          public void increasePriceOfAllProductsInCategory(final String 
            category) {
          TransactionTemplate transactionTemplate =
          new TransactionTemplate(this.transactionManager);
          transactionTemplate.setPropagationBehavior(TransactionDefinition
              .PROPAGATION_REQUIRED);
          transactionTemplate.execute(
          new TransactionCallbackWithoutResult() {
          public void doInTransactionWithoutResult(TransactionStatus 
            status) {
          List productsToChange = productDAO.loadProductsByCategory(category);
          ...
          }
          }
          );
          }
          }

          6. 聲明性事務(wù)劃分

                 我們還可以選擇使用Spring的AOP TransactionInterceptor通過在應(yīng)用配置中定義攔截器配置來代替事務(wù)劃分代碼的事務(wù)處理方式。這允許我們保持業(yè)務(wù)對(duì)象獨(dú)立于每個(gè)業(yè)務(wù)對(duì)象中重復(fù)的事務(wù)劃分代碼。此外,事務(wù)行為和隔離層次的變化可以通過一個(gè)配置文件來改變而不需要對(duì)業(yè)務(wù)對(duì)象的實(shí)現(xiàn)造成影響。

          <beans>
          
          ...
          
          <bean id="myTransactionManager"
                class="org.springframework.orm.hibernate
          .HibernateTransactionManager">
          <property name="sessionFactory">
          <ref bean="mySessionFactory"/>
          </property>
          </bean>
          
          <bean id="myTransactionInterceptor"
                class="org.springframework.transaction
          .interceptor.TransactionInterceptor">
          <property name="transactionManager">
          <ref bean="myTransactionManager"/>
          </property>
          <property name="transactionAttributeSource">
          <value>
          product.ProductService.increasePrice*=PROPAGATION_REQUIRED
          product.ProductService.someOtherBusinessMethod=
          PROPAGATION_MANDATORY
          </value>
          </property>
          </bean>
          
          <bean id="myProductServiceTarget" class="product
          .ProductServiceImpl">
          <property name="productDao">
          <ref bean="myProductDao"/>
          </property>
          </bean>
          
          <bean id="myProductService" class="org.springframework.aop
          .framework.ProxyFactoryBean">
          <property name="proxyInterfaces">
          <value>product.ProductService</value>
          </property>
          <property name="interceptorNames">
          <list>
          <value>myTransactionInterceptor</value>
          <value>myProductServiceTarget</value>
          </list>
          </property>
          </bean>
          
          </beans>

           
          public class ProductServiceImpl implements ProductService {
          
          private ProductDao productDao;
          
          public void setProductDao(ProductDao productDao) {
          this.productDao = productDao;
          }
          
          public void increasePriceOfAllProductsInCategory(final String
           category) {
          List productsToChange = this.productDAO
          .loadProductsByCategory(category);
          ...
          }
          }

                如同使用HibernateInterceptor一樣,TransactionInterceptor允許任何checked application exception從回調(diào)代碼中拋出,而TransactionTemplate受回調(diào)限制在其內(nèi)部拋出unchecked exceptions,在出現(xiàn)一個(gè)unchecked application exception的情況時(shí),TransactionTemplate將引發(fā)一個(gè)回滾或者這個(gè)事務(wù)由應(yīng)用(通過事務(wù)狀態(tài))標(biāo)記為回滾。TransactionInterceptor默認(rèn)情況也是同樣的行為,但是允許為每一個(gè)方法制定回滾策略。
                 建立聲明性事務(wù)的一個(gè)便利的方式是使用TransactionProxyFactoryBean,特別是如果沒有其他AOP攔截器的話,TransactionProxyFactoryBean將聯(lián)合定義為代理的自身與一個(gè)特殊的目標(biāo)Bean的事務(wù)配置。這將減少一個(gè)代理Bean對(duì)應(yīng)一個(gè)目標(biāo)Bean的配置情況。此外,你不必指定哪個(gè)接口或者哪個(gè)類必須定義事務(wù)方法。

          <beans>
          
          ...
          
          <bean id="myTransactionManager"
                class="org.springframework.orm.hibernate
          .HibernateTransactionManager">
          <property name="sessionFactory">
          <ref bean="mySessionFactory"/>
          </property>
          </bean>
          
          <bean id="myProductServiceTarget" class="product
          .ProductServiceImpl">
          <property name="productDao">
          <ref bean="myProductDao"/>
          </property>
          </bean>
          
          <bean id="myProductService"
                class="org.springframework.transaction.interceptor
          .TransactionProxyFactoryBean">
          <property name="transactionManager">
          <ref bean="myTransactionManager"/>
          </property>
          <property name="target">
          <ref bean="myProductServiceTarget"/>
          </property>
          <property name="transactionAttributes">
          <props>
          <prop key="increasePrice*">PROPAGATION_REQUIRED</prop>
          <prop key="someOtherBusinessMethod">PROPAGATION_MANDATORY</prop>
          </props>
          </property>
          </bean>
          
          </beans>
          

          7. 事務(wù)管理策略

                    對(duì)于Hibernate應(yīng)用來說,無論是TransactionTemplate還是TransactionInterceptor都是委托驗(yàn)實(shí)際的事務(wù)處理給PlatformTransactionManager實(shí)例,可以是一個(gè)HibernateTransactionManager(由一個(gè)單一的Hibernate的SessionFactory,使用一個(gè)ThreadLocal Session)或者可以是一個(gè)JtaTransactionManager(代理容器的JTA子系統(tǒng))。甚至你可以使用一個(gè)自定義的PlatformTransactionManager實(shí)現(xiàn)。
                 如果選擇從本地Hibernate事務(wù)管理轉(zhuǎn)為由JTA來進(jìn)行事務(wù)管理,例如:當(dāng)你的應(yīng)用的部署面對(duì)分布的事務(wù)需求時(shí),也僅僅是改變一下配置的事。只要簡(jiǎn)單地將Hibernate的事務(wù)管理換為JTA事務(wù)實(shí)現(xiàn)即可。所有的事務(wù)劃分和數(shù)據(jù)訪問無需做任何變動(dòng)仍可以繼續(xù)工作,因?yàn)樗麄兪褂玫亩际瞧胀ǖ氖聞?wù)管理API。
                 對(duì)于分布式的事務(wù)會(huì)跨越多個(gè)Hibernate的session factories,僅僅是聯(lián)合JtaTransactionManager與多個(gè)LocalSessionFactoryBean定義作為事務(wù)策略。你的每一個(gè)DAO將通過它們各自的Bean屬性得到一個(gè)特殊的SessionFactory的引用。如果這一切都是在下面的JDBC數(shù)據(jù)源是事務(wù)容器,一個(gè)業(yè)務(wù)對(duì)象可以劃分事務(wù)跨越很多DAO和很多session factories而無需做特別的處理,對(duì)于使用JtaTransactionManager做為事務(wù)策略也是一樣的。

           
          <beans>
          
          <bean id="myDataSource1" class="org.springframework.jndi
          .JndiObjectFactoryBean">
          <property name="jndiName">
          <value>jdbc/myds1</value>
          </property>
          </bean>
          
          <bean id="myDataSource2" class="org.springframework.jndi.
          JndiObjectFactoryBean">
          <property name="jndiName">
          <value>jdbc/myds2</value>
          </property>
          </bean>
          
          <bean id="mySessionFactory1"
                class="org.springframework.orm.hibernate.
          LocalSessionFactoryBean">
          <property name="mappingResources">
          <list>
          <value>product.hbm.xml</value>
          </list>
          </property>
          <property name="hibernateProperties">
          <props>
          <prop key="hibernate.dialect">net.sf.hibernate.dialect.
          MySQLDialect</prop>
          </props>
          </property>
          <property name="dataSource">
          <ref bean="myDataSource1"/>
          </property>
          </bean>
          
          <bean id="mySessionFactory2"
                class="org.springframework.orm.hibernate.
          LocalSessionFactoryBean">
          <property name="mappingResources">
          <list>
          <value>inventory.hbm.xml</value>
          </list>
          </property>
          <property name="hibernateProperties">
          <props>
          <prop key="hibernate.dialect">net.sf.hibernate.
          dialect.OracleDialect</prop>
          </props>
          </property>
          <property name="dataSource">
          <ref bean="myDataSource2"/>
          </property>
          </bean>
          
          <bean id="myTransactionManager"
                class="org.springframework.transaction.jta.
          JtaTransactionManager"/>
          
          <bean id="myProductDao" class="product.ProductDaoImpl">
          <property name="sessionFactory">
          <ref bean="mySessionFactory1"/>
          </property>
          </bean>
          
          <bean id="myInventoryDao" class="product.InventoryDaoImpl">
          <property name="sessionFactory">
          <ref bean="mySessionFactory2"/>
          </property>
          </bean>
          
          <bean id="myProductServiceTarget" class="product.
          ProductServiceImpl">
          <property name="productDao">
          <ref bean="myProductDao"/>
          </property>
          <property name="inventoryDao">
          <ref bean="myInventoryDao"/>
          </property>
          </bean>
          
          <bean id="myProductService"
                class="org.springframework.transaction.interceptor.
          TransactionProxyFactoryBean">
          <property name="transactionManager">
          <ref bean="myTransactionManager"/>
          </property>
          <property name="target">
          <ref bean="myProductServiceTarget"/>
          </property>
          <property name="transactionAttributes">
          <props>
          <prop key="increasePrice*">PROPAGATION_REQUIRED</prop>
          <prop key="someOtherBusinessMethod">PROPAGATION_MANDATORY</prop>
          </props>
          </property>
          </bean>
          
          </beans>

                 無論是HibernateTransactionManager還是JtaTransactionManager允許適當(dāng)?shù)膶?duì)Hibernate的在JVM層次的緩存處理-不需要容器-提供特殊的事務(wù)查找或者JCA連接器(只要不使用EJB發(fā)起事務(wù))。另外,HibernateTransactionManager能輸出JDBC連接供通常的JDBC訪問代碼使用。這樣就允許在高層次上的事務(wù)劃分是混合了Hibernate與JDBC而不要JTA的,只要只是訪問一個(gè)數(shù)據(jù)庫就可以!

          8. 使用Spring管理應(yīng)用的Bean

                  一個(gè)Spring應(yīng)用配置定義可以被多種配置實(shí)現(xiàn)所加載,從FileSystemXmlApplicationContext和ClassPathXmlApplicationContext到XmlWebApplicationContext。這就允許在各種環(huán)境下重用Spring管理的數(shù)據(jù)訪問和業(yè)務(wù)對(duì)象。默認(rèn)情況下,一個(gè)Web應(yīng)用將有它自己的定義在“WEB-INF/applicationContext.xml”中的根配置。
                 在任何一個(gè)Spring應(yīng)用中,一個(gè)應(yīng)用配置定義在一個(gè)XML格式的文件中用來對(duì)應(yīng)用的所有有關(guān)的Bean進(jìn)行裝配,從Hibernate的session factory到自定義的數(shù)據(jù)訪問和業(yè)務(wù)對(duì)象(象上面所有的Bean那樣)。他們中的大多數(shù)不需要Spring容器知道他們,甚至即使是與其他Bean合作時(shí)也一樣,因?yàn)樗麄冎皇呛?jiǎn)單的JavaBean之間的協(xié)作。下面的Bean定義可能是一個(gè)Spring Web 的MVC配置中用來訪問業(yè)務(wù)對(duì)象的配置的一部分。

           
          <bean id="myProductList" class="product.ProductListController">
          <property name="productService">
          <ref bean="myProductService"/>
          </property>
          </bean>

                Spring的Web控制器經(jīng)由Bean引用擁有它們需要的所有的業(yè)務(wù)和數(shù)據(jù)訪問對(duì)象,因此它們無需在應(yīng)用配置中做任何手工的Bean查找。但是當(dāng)使用Spring管理的Beans用于Struts或者是在EJB實(shí)現(xiàn),或者一個(gè)applet中時(shí)常常是需要必須手工查找一個(gè)Bean的。因此Spring的Bean可以被用在任何地方。也許只是需要是一應(yīng)用配置的引用,或者經(jīng)由一個(gè)web容器的Servlet配置屬性,或者從一個(gè)文件中或者類路徑的資源中創(chuàng)建它。

          ApplicationContext context =WebApplicationContextUtils.
          getWebApplicationContext(servletContext);
          ProductService productService =
          (ProductService) context.getBean("myProductService");

           ApplicationContext context =
          new FileSystemXmlApplicationContext("C:/myContext.xml");
          ProductService productService =
          (ProductService) context.getBean("myProductService");
          

           ApplicationContext context =
          new ClassPathXmlApplicationContext("myContext.xml");
          ProductService productService =
          (ProductService) context.getBean("myProductService");

          9. 容器資源VS本地資源

                 Spring的資源管理允許簡(jiǎn)單地在一個(gè)JNDI SessionFactory和一個(gè)本地SessionFactory間做選擇,同樣允許在一個(gè)JNDI DataSource與本地DataSource間做選擇,而無需改變應(yīng)用的一行代碼。在容器中保存資源定義還是在應(yīng)用本地保存,主要是一個(gè)事務(wù)策略方面的事。比較一個(gè)Spring定義的本地SessionFactory與一個(gè)手工注冊(cè)的JNDI SessionFactory沒有任何益處。如果經(jīng)由Hibernate的JCA連接器注冊(cè),才會(huì)有加入JTA事務(wù)的明顯益處,特別是對(duì)EJB。

                 一個(gè)重要的Spring事務(wù)提供的好處是它不與任何容器綁定。定義包括JTA在內(nèi)的策略,它都可以獨(dú)立工作或者在一個(gè)試驗(yàn)環(huán)境中工作。特別是對(duì)典型的一個(gè)數(shù)據(jù)庫的事務(wù)來說,對(duì)于JTA這是一個(gè)非常輕量的和強(qiáng)大的選擇。當(dāng)使用本地EJB SLSB的事務(wù)時(shí),你將同時(shí)依賴EJB容器和JTA-即使你只是訪問一個(gè)數(shù)據(jù)庫,即使只是使用SLSBs經(jīng)由CMT來聲明事務(wù)。選擇使用 JTA編程也需要一個(gè)J2EE環(huán)境。

                 就JTA自身和JNDI數(shù)據(jù)源來說JTA不只是包括容器依賴。對(duì)于不使用Spring的JTA驅(qū)動(dòng)的Hibernate事務(wù),你必須使用HibernateJCA連接器或者在合適的JVM緩沖層專門寫Hibernate的事務(wù)代碼配置JTA事務(wù)。在只訪問一個(gè)數(shù)據(jù)庫的情況下,Spring驅(qū)動(dòng)的事務(wù)可以與一個(gè)本地定義的Hibernate的SessionFactory配合良好,就如同與一個(gè)本地JDBC數(shù)據(jù)源相配合一樣。因此當(dāng)面對(duì)分布的事務(wù)需求時(shí),你只需要轉(zhuǎn)換為Spring的JTA事務(wù)策略即可。

                 要注意一個(gè)JCA連接器需要特別的容器的部署步驟,并且顯然首先得支持JCA。這比使用本地資源定義和Spring驅(qū)動(dòng)事務(wù)來部署一個(gè)簡(jiǎn)單的Web應(yīng)用有更多的爭(zhēng)議。而且你常常需要企業(yè)版本的容器支持,象WebLogic Express就不提供JCA。一個(gè)只用一個(gè)數(shù)據(jù)庫的使用本地資源和事務(wù)的Spring應(yīng)用可以在任何J2EE的Web容器中工作,Web容器不必支持JTA, JCA和EJB,如:Tomcat, Resin甚至最小的Jetty。另外,這樣一個(gè)中間層就可以很容易地在桌面應(yīng)用或者在測(cè)試套件中被重用。

                 所有考慮過的事情包括:如果你不使用EJB,堅(jiān)持使用本地SessionFactory,使用SpringHibernateTransactionManager或者JtaTransactionManager,你將獲得包括適當(dāng)處理的JVM層的緩存和分布事務(wù)的所有益處,而無需引起任何關(guān)于容器部署的爭(zhēng)論。經(jīng)由JCA連接器的一個(gè)Hibernate的SessionFactory的JNDI注冊(cè)只是在使用EJB的情況中才會(huì)有明顯的附加值。


          10. Skeletons和例子

                配置使用Spring和HIbernate的一個(gè)J2EE的Web應(yīng)用的注釋和細(xì)節(jié)最好去看看在Spring Framework的例子中的“典型的Web應(yīng)用”Skeletons,它給出了適合于JDBC 和 Hibernate應(yīng)用的多種數(shù)據(jù)源及事務(wù)管理的配置項(xiàng),仔細(xì)看一下事務(wù)攔截器的配置,它也同樣向你展示了如何配置AOP攔截器。

                在Spring的1.0 M2版中,例子Petclinic提供了JDBC和Hibernate的DAO實(shí)現(xiàn)和應(yīng)用配置的選擇。Petclinic
          可以作為一個(gè)可工作的簡(jiǎn)單應(yīng)用說明如何在一個(gè)Spring web 應(yīng)用中使用Hibernate,同樣也包括根據(jù)不同的事務(wù)策略來聲明事務(wù)劃分。

          Links

          Spring Framework website

          Spring Framework documentation


          作者Blog:http://blog.csdn.net/welcomyou/
          posted on 2005-03-21 00:44 笨笨 閱讀(328) 評(píng)論(0)  編輯  收藏 所屬分類: HibernateAndSpringALL
          主站蜘蛛池模板: 孟津县| 阿坝县| 肥城市| 东莞市| 凤阳县| 南漳县| 西宁市| 高清| 赣州市| 郧西县| 开阳县| 忻城县| 监利县| 蚌埠市| 赣州市| 集安市| 阜城县| 高雄市| 陆良县| 屏南县| 汪清县| 昌吉市| 清新县| 奉贤区| 左贡县| 临江市| 泸州市| 克东县| 当阳市| 桃园市| 龙海市| 泸水县| 伊通| 克什克腾旗| 临安市| 湘潭市| 万州区| 康马县| 望谟县| 景洪市| 安岳县|