最近工作中涉及到一些將其他項目組的應用整合到我們平臺上的事情。剛好那個項目是base在Appfuse提供的框架基礎上開發的。使用了Spring2.0 + Struts2.0 + Ibatis的框架。趁此機會把這幾個外面現在比較流行的東西又好好看了看。現在寫個總結。也希望能便于以后的參考。好了,元歸正傳,開始我們的SSI之旅。
我們還是從代碼講起。這樣也便于我們理解。否則High Level的東西說了一通到最后也不知道都說明了什么。
先看幾段代碼:
Spring DataSoure:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxActive" value="${jdbc.maxActive}"/>
<property name="maxIdle" value="${jdbc.maxIdle}"/>
<property name="maxWait" value="${jdbc.maxWait}"/>
<property name="defaultAutoCommit" value="true"/>
<property name="removeAbandoned" value="true"/>
<property name="removeAbandonedTimeout" value="60"/>
<!-- 以下配置用于開發時追蹤沒有釋放數據庫連接的代碼,部署時應刪除 -->
<property name="logAbandoned" value="true"/>
</bean>
這里我們使用dbcp連接池。這里就不多說了。
Spring AOP Configuration:
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
</bean>
<tx:advice id="txAdvice" transaction-manager="txManager">
<!-- the transactional semantics... -->
<tx:attributes>
<!-- all methods starting with 'get' are read-only -->
<tx:method name="get*" read-only="true" />
<!-- other methods use the default transaction settings (see below) -->
<tx:method name="*" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="serviceOperation"
expression="execution(* com.ibm.magis..service.*Manager.*(..))" />
<aop:advisor advice-ref="txAdvice"
pointcut-ref="serviceOperation" />
</aop:config>
這里就和我們以前用的Spring就不一樣了。這里我們使用的是AspectJ 的切面事務的統一控制。 Spring的官方文檔說:“如果你選擇使用Spring AOP,那么你可以選擇@AspectJ或者XML風格。總的來說,如果你使用Java 5,我們建議使用@AspectJ風格。”當然項目中使用的是JDK1.5 所以他使用了這樣的聲明方式。
回頭看一下我們以前的方法:
<bean id="txProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="remove*">PROPAGATION_REQUIRED,-Exception </prop>
<prop key="update*">PROPAGATION_REQUIRED,-Exception </prop>
<prop key="incress*">PROPAGATION_REQUIRED,-Exception </prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
兩者相比較而言還是AspectJ的這種風格比較好。而且我們可以方邊在Spring中定義我們自己的切面。例如日志的記錄、權限的檢查等等。
<aop:config>
<aop:aspect id="objectACLAspectU" ref="objectACLAdviceU">
<aop:pointcut id="objectRemovePcU" expression="execution(* com.ibm.magis.data.instance.service.OinstanceManager.remove(..)) and args(objectId,instanceId)"/>
</aop:aspect>
</aop:config>
<bean id="objectACLAdviceU" class="com.ibm.magis.acl.advice.ObjectACLUsingAdvice">
<property name="oinstanceManager" ref="oinstanceManager"/>
<property name="objectACLManager" ref="objectACLManager"/>
</bean>
經過簡單的配置在加上一個簡單的實現類就可以完成一些復雜的切面控制的代碼了。
看完上面Spring2.0的AOP后。在看一個配置文件:
<beans default-autowire="byName" default-lazy-init="true">
<bean id="objectACLDao" class="com.ibm.magis.acl.dao.ibatis.PObjectACLDaoImpl" />
</beans>
注意這個屬性default-lazy-init. 如果設置為true 則表明Spring 的IOC容器使用Lazy-load的方式進行加載。這種懶加載的方式可從某種情況下提高啟動的速度。但是也會有一個問題哦。可能不會馬上發現配置錯誤的bean.
還有一個屬性:default-autowire="byName" 設置Spring的自動裝配方式。autowire的方便之處在減少或者消除屬性或構造器參數的設置,這樣可以給我們的配置文件減減肥!
載至Spring官方文檔
模式
|
說明
|
no
|
不使用自動裝配。必須通過ref元素指定依賴,這是默認設置。由于顯式指定協作者可以使配置更靈活、更清晰,因此對于較大的部署配置,推薦采用該設置。而且在某種程度上,它也是系統架構的一種文檔形式。
|
byName
|
根據屬性名自動裝配。此選項將檢查容器并根據名字查找與屬性完全一致的bean,并將其與屬性自動裝配。例如,在bean定義中將autowire設置為by name,而該bean包含master屬性(同時提供setMaster(..)方法),Spring就會查找名為master的bean定義,并用它來裝配給master屬性。
|
byType
|
如果容器中存在一個與指定屬性類型相同的bean,那么將與該屬性自動裝配。如果存在多個該類型的bean,那么將會拋出異常,并指出不能使用byType方式進行自動裝配。若沒有找到相匹配的bean,則什么事都不發生,屬性也不會被設置。如果你不希望這樣,那么可以通過設置dependency-check="objects"讓Spring拋出異常。
|
constructor
|
與byType的方式類似,不同之處在于它應用于構造器參數。如果在容器中沒有找到與構造器參數類型一致的bean,那么將會拋出異常。
|
autodetect
|
通過bean類的自省機制(introspection)來決定是使用constructor還是byType方式進行自動裝配。如果發現默認的構造器,那么將使用byType方式。
|
這也是一個不錯的地方。可以省去我們很多地方配置的顯示聲明。
我們可以看一下Struts2.0的使用吧。個人認為其實Struts2.0就是完全照搬的webwork的。沒有多少自己的心意。
具體的配置就不多說了。主要是看看下面這個配置文件:
<constant name="struts.i18n.encoding" value="UTF-8"/>
<constant name="struts.action.extension" value="action"/>
<constant name="struts.objectFactory" value="spring"/>
注意<constant name="struts.objectFactory" value="spring"/>
這里它將框架常量struts.objectFactory覆蓋了,設置為”spring”,其實這里是使用了縮寫,我們可以寫全稱:org.apache.struts2.spring.StrutsSpringObjectFactory。這個縮寫的”spring”是和bean配置中的name屬性相對應的。默認情況下所有由框架創建的對象都是由ObjectFactory實例化的,ObjectFactory提供了與其它IoC容器如Spring、Pico等集成的方法。覆蓋這個ObjectFactory的類必須繼承ObjectFactory類或者它的任何子類,并且要帶有一個不帶參數的構造方法。在這里我們用org.apache.struts2.spring.StrutsSpringObjectFactory代替了默認的ObjectFactory。
此外,上面我們說了,如果action不是使用Spring ObjectFactory創建的話,插件提供了兩個攔截器來自動裝配action,默認情況下框架使用的自動裝配策略是name,也就是說框架會去Spring中尋找與action屬性名字相同的bean,可選的裝配策略還有:type、auto、constructor,我們可以通過常量struts.objectFactory.spring.autoWire來進行設置。
這樣的話,我們就可以在Action中使用Spring IOC中注入的Bean了。其實這是webwork早有的擴展包里的功能。呵呵。換成strut2.0了還是得說一下。
有了上面的配置文件我們就可以把Spring2.0 和 struts2.0 結合起來了。
看看IBatis 的配置文件:
<!-- SqlMap setup for iBATIS Database Layer -->
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation">
<value>classpath:/sql-map-config.xml</value>
</property>
<property name="dataSource" ref="dataSource"/>
</bean>
其實配置這個sqlMapClient在Spring中也是眾所周知的事情了。有了ByName的自動裝配功能。我們也不需要在各個DAO中顯示的ref 這個bean 了。
具體Ibatis的使用請參考 Ibatis官方網站:http://ibatis.apache.org
from:http://m.tkk7.com/anwenhao/archive/2007/12/29/171610.html
Tags: struts2 struts ibatis 總結 spring2
原創文章如轉載,請注明:轉載自:飛揚部落編程倉庫 : http://www.busfly.cn/csdn/
本文鏈接地址:http://www.busfly.cn/csdn/post/Sping2-Struts2-Ibatis,.html