Spring+hibernate實戰(二)

          項目很小,主體部分也完成的差不多了,但麻雀雖小,五臟具全,我在其中用到了springIoCtransaction管理,也用到了簡單的AOP功能,同時使用了spring mvc,下面我對它們做一些總結,也跟和我一樣剛剛踏入spring大門的兄弟們探討探討:

          (一)spring IoC探討

          先還是談談spring IoC的使用。IoC也就是控制反轉,即由容器來調用你的代碼,而你不用去使用容器的接口,一般都用好萊塢原則來進行形象的比喻。最近在看那本without EJB才知道其實DI(依賴注入)其實只是IoC的一種實現,而DI又分為set注入和constructor注入。更輕量級的IoC容器PicoContainer就是采用constructor注入,spring兩種都支持,但Rod Johnson經過詳細的比較,建議還是一般采用set注入方式。理解set注入,對使用和深入了解spring框架非常重要。

          為了做到面向接口編程,我們總是盡量使用接口聲明,但接口是不能new的,如果不使用IoC容器,終歸需要個地方new它的實現類。如Interface a=new InterfaceImpl(),這樣還是在代碼中形成了對實現類的依賴。當然我們可以使用factory模式來將聲明提取到工廠類中,但這樣又形成了對工廠的依賴,而且工廠也會越來越多,不便于管理。于是我們通過配置如

           

          <bean id="emailAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

          這樣在配置文件中聲明其實現類,就消除了對具體實現類的耦合。而一個類通常需要放置其它類的引用,或者使用從其它配置文件讀出的值,這個時候就是set注入顯示威力的時候了。

          <bean id="msg" class="org.springframework.mail.SimpleMailMessage">

                 
          <property name="from" value="${mail.from}" />

              bean>這是聲明一個Message對象實例的配置文件,${mail.from}表明是在*.properties文件配置的值,看到這個我們就知道SimpleMailMessage是一個具體類,有一個from的屬性,同時有一個setFrom的公共方法。SpringContextLoader在啟動時就會自動創建一個SimpleMailMessage對象的實例,并將mail.from對應的值用set方法注入進去,spring默認會創建Singleton對象。以后碰到需要配置的什么參數,就可以采用這種方式注入,注意.properties文件還是分個類較好,如jdbc.properties配置數據庫訪問參數,mail.properties配置郵件參數(我這也是學的jpetstore的)。

          以下配置就是將一個mailSender和一個msg引用注入到一個emailAdvice中去。emailAdvice使用的是他們的接口聲明,然后加上set方法,而不關心它們是用什么實現類。

          <bean id="emailAdvice" class="com.bankcomm.vpn.service.SendMailAdvice">

                 
          <property name="mailSender" ref="mailSender" />

                 
          <property name="msg" ref="msg" />

          </bean
          >

          講一個巧妙使用spring set注入解決實際問題的例子。系統要求某些用戶有審批的權限,通常我們使用數據庫,但由于是小項目,能審批的用戶也不多,我又不想寫什么Dao,于是希望能在配置文件中直接定義。如果不使用spring,在以往項目中的做法就是定義一個xml文件,然后寫方法去解析文件,把配置的用戶讀取到一個config類中,這個過程又必須在系統啟動時進行,所以有個StarterServlet,在啟動后調用這個方法,StarterServlet又需要定義在web.xml中。是不是很復雜?

          有了spring,我們就有了新的選擇。先看下面的配置文件:

                

          <bean id="auditer" class="com.bankcomm.vpn.service.Auditer">

                     
          <property name="auditers">

                        
          <list>

                            
          <value>info1value>

                          
          <value>info2value>

                           

                        
          </list>

                     
          </property>

                 
          </bean>

          為簡單起見,我沒有使用接口,直接定義了一個Auditer類,它有一個List類型的auditers屬性,然后加個set方法。對auditers里面的值,就使用spring支持的list配置方式進行注入。你可以配多個valuecontextLoader啟動時就會自動把這些value填入一個ArrayList實現,然后setauditer類中,你就可以直接使用這個類了。你看,是不是很方便就實現了這個功能,這也從一個方面體現了spring的強大之處。

          (二)spring transaction管理探討

          說到transaction管理,其實我也沒有太多經驗(項目經驗太少!),以前寫jdbc代碼,就是使用setAutoCommit(false)來實現,要用到JTA來實現跨數據庫的情況還沒碰到過。所以這里就簡單講講如何寫spring配置文件來支持transaction的聲明式配置。

          <bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"

                   
          abstract="true">

                 
          <property name="transactionManager" ref="transactionManager"/>

                 
          <property name="transactionAttributes">

                     
          <props>

                        
          <prop key="insert*">PROPAGATION_REQUIRED</prop>

                        
          <prop key="update*">PROPAGATION_REQUIRED</prop>

                        
          <prop key="*">PROPAGATION_REQUIRED,readOnlyprop>

                     
          </props>

                 
          </property>

              
          </bean>

          以上配置文件就是定義了一個baseTransactionProxy 對象,它注入一個transactionManager對象,并注入一個transactionAttributesProperties對象,這個Properties對象的配置就是內配置的內容。transactionManager可以根據你的需要來進行配置,如使用hibernate,可以用

          <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"><property name="sessionFactory" ref="sessionFactory"/></bean>

          來配置。如果使用JTA就使用

          <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>

          這里很方便就能切換到另一種transactionManager的實現上去。PROPAGATION_REQUIRED表明會放入當前的事務中,如果沒有就創建一個。Readonly表明此方法只讀,能提高速度,spring還支持隔離級別的配置,具體配置說明,可以看springapi文檔http://www.springframework.org/docs/api/org/springframework/transaction/TransactionDefinition.html

          有了這個baseTransactionProxy,我們就可以用下面的配置使service層的Fa?ade對象具備事務管理功能了。這里VpnImpl 為一個Fa?ade接口的實現類,它實現對Dao層的代理然后,提供對外的統一接口。好處就是只有一個接口類,對transaction的配置和其它AOP配置都可以針對這個Fa?ade進行,希望詳細了解Fa?ade模式可以參看模式相關書籍。

          <bean id="vpn" parent="baseTransactionProxy">

                 
          <property name="target">

                     
          <bean class="com.bankcomm.vpn.service.VpnImpl">

                        
          <property name="userDao" ref="userDao" />

                        
          <property name="submitVpnRequest" ref="submitVpnRequest" />

                     
          </bean>

                 
          </property>

                 
          <property name="postInterceptors">

                     
          <list>

                        
          <ref bean="emailAdvisor" />

                     
          </list>

                 
          </property>

              
          </bean>

          有了springtransaction管理,聲明式事務就不再是EJB所獨有了,我們可以使用spring的事務,而避免僅僅因為要聲明式事務而使用EJB這樣重量級的東西了。

                 先寫到這里吧,下篇我再繼續AOPspring mvc的討論。

          posted on 2005-11-07 16:02 pesome 閱讀(2559) 評論(0)  編輯  收藏 所屬分類: Spring+Struts+Hibernate

          <2005年11月>
          303112345
          6789101112
          13141516171819
          20212223242526
          27282930123
          45678910

          導航

          統計

          公告

          主要記錄作者在學習java中的每一步足跡。除非特別說明,所有文章均為本blog作者原創,如需轉載請注明出處和原作者,如用于商業目的,需跟作者本人聯系。
          歡迎大家訪問:

          常用鏈接

          留言簿(16)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          相冊

          收藏夾

          java技術

          人間百態

          朋友們的blog

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 太谷县| 枣庄市| 肥东县| 天门市| 平利县| 嵊泗县| 巴东县| 赤壁市| 滨海县| 涡阳县| 罗源县| 修武县| 新绛县| 壤塘县| 阿拉善左旗| 凌海市| 合山市| 辽中县| 呈贡县| 大港区| 资源县| 西宁市| 锡林郭勒盟| 丘北县| 博野县| 睢宁县| 涟源市| 天柱县| 沧源| 石家庄市| 进贤县| 如皋市| 九江市| 富裕县| 利津县| 海兴县| 沐川县| 三明市| 临汾市| 毕节市| 淅川县|