spring搴旂敤 浜嬪姟瀛︿範二 璇︾粏瀛︿範

spring搴旂敤 浜嬪姟瀛︿範2 璇︾粏瀛︿範

9.5. 澹版槑寮忎簨鍔$鐞?/p>

澶у鏁癝pring鐢ㄦ埛閫夋嫨澹版槑寮忎簨鍔$鐞嗐€傝繖鏄搴旂敤浠g爜褰卞搷鏈€灏忕殑閫夋嫨锛屽洜姝や篃鏈€绗﹀悎 闈炰镜鍏ュ紡 杞婚噺绾у鍣ㄧ殑鐞嗗康銆?/p>

Spring鐨勫0鏄庡紡浜嬪姟绠$悊鏄€氳繃Spring AOP瀹炵幇鐨勶紝鍥犱负浜嬪姟鏂归潰鐨勪唬鐮佷笌Spring缁戝畾骞朵互涓€绉嶆牱鏉垮紡椋庢牸浣跨敤锛屼笉杩囧敖绠″姝わ紝浣犱竴鑸苟涓嶉渶瑕佺悊瑙OP姒傚康灏卞彲浠ユ湁鏁堝湴浣跨敤Spirng鐨勫0鏄庡紡浜嬪姟绠$悊銆?/p>

浠庤€冭檻EJB CMT鍜孲pring澹版槑寮忎簨鍔$鐞嗙殑鐩镐技浠ュ強涓嶅悓涔嬪鍑哄彂鏄緢鏈夌泭鐨勩€傚畠浠殑鍩烘湰鏂规硶鏄浉浼肩殑锛氶兘鍙互鎸囧畾浜嬪姟绠$悊鍒板崟鐙殑鏂规硶锛涘鏋滈渶瑕佸彲浠ュ湪浜嬪姟涓婁笅鏂囪皟鐢?setRollbackOnly() 鏂规硶銆備笉鍚屼箣澶勫湪浜庯細

涓嶅儚EJB CMT缁戝畾鍦↗TA涓婏紝Spring澹版槑寮忎簨鍔$鐞嗗彲浠ュ湪浠讳綍鐜涓嬩娇鐢ㄣ€傚彧闇€鏇存敼閰嶇疆鏂囦欢锛屽畠灏卞彲浠ュ拰JDBC銆丣DO銆丠ibernate鎴栧叾浠栫殑浜嬪姟鏈哄埗涓€璧峰伐浣溿€?/p>

Spring鐨勫0鏄庡紡浜嬪姟绠$悊鍙互琚簲鐢ㄥ埌浠讳綍绫伙紙浠ュ強閭d釜绫荤殑瀹炰緥锛変笂锛屼笉浠呬粎鏄儚EJB閭f牱鐨勭壒娈婄被銆?/p>

Spring鎻愪緵浜嗗0鏄庡紡鐨勫洖婊氳鍒欙細EJB娌℃湁瀵瑰簲鐨勭壒鎬э紝鎴戜滑灏嗗湪涓嬮潰璁ㄨ銆傚洖婊氬彲浠ュ0鏄庡紡鐨勬帶鍒讹紝涓嶄粎浠呮槸缂栫▼寮忕殑銆?/p>

Spring鍏佽浣犻€氳繃AOP瀹氬埗浜嬪姟琛屼负銆備緥濡傦紝濡傛灉闇€瑕侊紝浣犲彲浠ュ湪浜嬪姟鍥炴粴涓彃鍏ュ畾鍒剁殑琛屼负銆備綘涔熷彲浠ュ鍔犱换鎰忕殑閫氱煡锛屽氨璞′簨鍔¢€氱煡涓€鏍枫€備娇鐢‥JB CMT锛岄櫎浜嗕娇鐢╯etRollbackOnly()锛屼綘娌℃湁鍔炴硶鑳藉褰卞搷瀹瑰櫒鐨勪簨鍔$鐞嗐€?/p>

Spring涓嶆彁渚涢珮绔簲鐢ㄦ湇鍔″櫒鎻愪緵鐨勮法瓒婅繙绋嬭皟鐢ㄧ殑浜嬪姟涓婁笅鏂囦紶鎾€傚鏋滀綘闇€瑕佽繖浜涚壒鎬э紝鎴戜滑鎺ㄨ崘浣犱娇鐢‥JB銆傜劧鑰岋紝涓嶈杞绘槗浣跨敤杩欎簺鐗规€с€傞€氬父鎴戜滑骞朵笉甯屾湜浜嬪姟璺ㄨ秺杩滅▼璋冪敤銆?/p>

TransactionProxyFactoryBean鍦ㄥ摢鍎匡紵

Spring2.0鍙婁互鍚庣殑鐗堟湰涓0鏄庡紡浜嬪姟鐨勯厤缃笌涔嬪墠鐨勭増鏈湁鐩稿綋澶х殑涓嶅悓銆備富瑕佸樊寮傚湪浜庝笉鍐嶉渶瑕侀厤缃甌ransactionProxyFactoryBean浜嗐€?/p>

Spring2.0涔嬪墠鐨勬棫鐗堟湰椋庢牸鐨勯厤缃粛鐒舵槸鏈夋晥鐨勶紱浣犲彲浠ョ畝鍗曞湴璁や负鏂扮殑<tx:tags/>鏇夸綘瀹氫箟浜員ransactionProxyFactoryBean銆?/p>

鍥炴粴瑙勫垯鐨勬蹇垫瘮杈冮噸瑕侊細瀹冧娇鎴戜滑鑳藉鎸囧畾浠€涔堟牱鐨勫紓甯革紙鍜宼hrowable锛夊皢瀵艰嚧鑷姩鍥炴粴銆傛垜浠湪閰嶇疆鏂囦欢涓0鏄庡紡鍦版寚瀹氾紝鏃犻』鍦↗ava浠g爜涓€傚悓鏃讹紝鎴戜滑浠嶆棫鍙互閫氳繃璋冪敤 TransactionStatus 鐨?setRollbackOnly() 鏂规硶缂栫▼寮忓湴鍥炴粴褰撳墠浜嬪姟銆傞€氬父锛屾垜浠畾涔変竴鏉¤鍒欙紝澹版槑 MyApplicationException 蹇呴』鎬绘槸瀵艰嚧浜嬪姟鍥炴粴銆傝繖绉嶆柟寮忓甫鏉ヤ簡鏄捐憲鐨勫ソ澶勶紝瀹冧娇浣犵殑涓氬姟瀵硅薄涓嶅繀渚濊禆浜庝簨鍔¤鏂姐€傚吀鍨嬬殑渚嬪瓙鏄綘涓嶅繀鍦ㄤ唬鐮佷腑瀵煎叆Spring API锛屼簨鍔$瓑銆?/p>

瀵笶JB鏉ヨ锛岄粯璁ょ殑琛屼负鏄疎JB瀹瑰櫒鍦ㄩ亣鍒?绯荤粺寮傚父锛堥€氬父鎸囪繍琛屾椂寮傚父锛夋椂鑷姩鍥炴粴褰撳墠浜嬪姟銆侲JB CMT閬囧埌 搴旂敤寮傚父锛堜緥濡傦紝闄や簡 java.rmi.RemoteException 澶栧埆鐨刢hecked exception锛夋椂骞朵笉浼氳嚜鍔ㄥ洖婊氥€傞粯璁ゅ紡Spring澶勭悊澹版槑寮忎簨鍔$鐞嗙殑瑙勫垯閬靛畧EJB涔犳儻锛堝彧鍦ㄩ亣鍒皍nchecked exceptions鏃惰嚜鍔ㄥ洖婊氾級锛屼絾閫氬父瀹氬埗杩欐潯瑙勫垯浼氭洿鏈夌敤銆?/p>

9.5.1. 鐞嗚ВSpring鐨勫0鏄庡紡浜嬪姟绠$悊瀹炵幇

鏈妭鐨勭洰鐨勬槸娑堥櫎涓庝娇鐢ㄥ0鏄庡紡浜嬪姟绠$悊鏈夊叧鐨勭绉樻€с€傜畝鍗曠偣鍎挎€绘槸濂界殑锛岃繖浠藉弬鑰冩枃妗e彧鏄憡璇変綘缁欎綘鐨勭被鍔犱笂@Transactional娉ㄨВ锛屽湪閰嶇疆鏂囦欢涓坊鍔狅紙'<tx:annotation-driven/>'锛夎锛岀劧鍚庢湡鏈涗綘鐞嗚В鏁翠釜杩囩▼鏄€庝箞宸ヤ綔鐨勩€傛鑺傝杩癝pring鐨勫0鏄庡紡浜嬪姟绠$悊鍐呴儴鐨勫伐浣滄満鍒讹紝浠ュ府鍔╀綘鍦ㄩ潰瀵逛簨鍔$浉鍏崇殑闂鏃朵笉鑷充簬璇叆杩烽€旓紝鍥炴湐鍒颁笂娓稿钩闈欑殑姘村煙銆?/p>

鎻愮ず

闃呰Spring婧愮爜鏄悊瑙f竻妤歋pring浜嬪姟鏀寔鐨勪竴涓ソ鏂规硶銆係pring鐨凧avadoc鎻愪緵鐨勪俊鎭赴瀵岃€屽畬鏁淬€傛垜浠缓璁綘鍦ㄥ紑鍙戣嚜宸辩殑Spring搴旂敤鏃舵妸鏃ュ織绾у埆璁句负'DEBUG'绾э紝杩欐牱浣犺兘鏇存竻妤氬湴鐪嬪埌骞曞悗鍙戠敓鐨勪簨銆?/p>

鍦ㄧ悊瑙pring鐨勫0鏄庡紡浜嬪姟绠$悊鏂归潰鏈€閲嶈鐨勬蹇垫槸锛歋pring鐨勪簨鍔$鐞嗘槸閫氳繃AOP浠g悊瀹炵幇鐨勩€傚叾涓殑浜嬪姟閫氱煡鐢卞厓鏁版嵁锛堢洰鍓嶅熀浜嶺ML鎴栨敞瑙o級椹卞姩銆備唬鐞嗗璞′笌浜嬪姟鍏冩暟鎹粨鍚堜骇鐢熶簡涓€涓狝OP浠g悊锛屽畠浣跨敤涓€涓狿latformTransactionManager瀹炵幇鍝侀厤鍚圱ransactionInterceptor锛屽湪鏂规硶璋冪敤鍓嶅悗瀹炴柦浜嬪姟銆?/p>

娉ㄦ剰

灏界浣跨敤Spring澹版槑寮忎簨鍔$鐞嗕笉闇€瑕丄OP锛堝挨鍏舵槸Spring AOP锛夌殑鐭ヨ瘑锛屼絾浜嗚В杩欎簺鏄緢鏈夊府鍔╃殑銆備綘鍙互鍦?绗?6 绔?浣跨敤Spring杩涜闈㈠悜鍒囬潰缂栫▼锛圓OP锛?绔犳壘鍒板叧浜嶴pring AOP鐨勫叏閮ㄥ唴瀹广€?/p>

姒傚康涓婃潵璇达紝鍦ㄤ簨鍔′唬鐞嗕笂璋冪敤鏂规硶鐨勫伐浣滆繃绋嬬湅璧锋潵鍍忚繖鏍凤細

9.5.2. 绗竴涓緥瀛?/p>

璇风湅涓嬮潰鐨勬帴鍙e拰瀹冪殑瀹炵幇銆傝繖涓緥瀛愮殑鎰忓浘鏄粙缁嶆蹇碉紝浣跨敤 Foo 鍜?Bar 杩欐牱鐨勫悕瀛楀彧鏄负浜嗚浣犲叧娉ㄤ簬浜嬪姟鐨勭敤娉曪紝鑰屼笉鏄鍩熸ā鍨嬨€?/p>

聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 <!-- 鎴戜滑鎯冲仛鎴愪簨鍔℃€х殑鏈嶅姟鎺ュ彛 -->

聽 聽 聽 聽 聽 聽聽

package x.y.service;
 
public interface FooService {
    Foo getFoo(String fooName);
    Foo getFoo(String fooName, String barName);
    void insertFoo(Foo foo);
    void updateFoo(Foo foo);
}
                
聽聽 聽 聽 聽 聽 聽 聽 聽 <!-- 涓婅堪鎺ュ彛鐨勪竴涓疄鐜?-->

聽 聽 聽 聽 聽 聽聽

package x.y.service;
 
public class DefaultFooService implements FooService {
    public Foo getFoo(String fooName) {
        throw new UnsupportedOperationException();
    }
    public Foo getFoo(String fooName, String barName) {
        throw new UnsupportedOperationException();
    }
    public void insertFoo(Foo foo) {
        throw new UnsupportedOperationException();
    }
    public void updateFoo(Foo foo) {
        throw new UnsupportedOperationException();
    }
}

锛堝璇ヤ緥鐨勭洰鐨勬潵璇达紝涓婁緥涓疄鐜扮被锛圖efaultFooService锛夌殑姣忎釜鏂规硶鍦ㄥ叾鏂规硶浣撲腑鎶涘嚭 UnsupportedOperationException 鐨勫仛娉曟槸鎭板綋鐨勶紝鎴戜滑鍙互鐪嬪埌锛屼簨鍔¤鍒涘缓鍑烘潵锛屽搷搴?UnsupportedOperationException 鐨勬姏鍑猴紝鐒跺悗鍥炴粴銆傦級聽

鎴戜滑鍋囧畾锛孎ooService鐨勫墠涓や釜鏂规硶锛坓etFoo(String)鍜実etFoo(String, String)锛夊繀椤绘墽琛屽湪鍙浜嬪姟涓婁笅鏂囦腑锛屽叾浣欐柟娉曪紙insertFoo(Foo)鍜寀pdateFoo(Foo)锛夊繀椤绘墽琛屽湪璇诲啓浜嬪姟涓婁笅鏂囦腑銆?/p>

浣跨敤XML鏂瑰紡鍏冩暟鎹殑澹版槑寮忛厤缃殑璇濓紝浣犲緱杩欎箞鍐欙紙涓嶈鎯崇潃涓€娆″叏閮ㄧ悊瑙o紝鎵€鏈夊唴瀹逛細鍦ㄥ悗闈㈢殑绔犺妭璇︾粏璁ㄨ锛夛細

<!-- 'context.xml'鏂囦欢鐨勫唴瀹瑰涓嬶細 -->
            
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
 
  <!-- 杩欐槸鎴戜滑灏嗚閰嶇疆骞朵娇瀹冨叿鏈変簨鍔℃€х殑Service瀵硅薄 -->
  
  <bean id="fooService" class="x.y.service.DefaultFooService"/>
 
  
  <!-- the transactional advice (i.e. what 'happens'; see the <aop:advisor/> bean below) -->
  
  <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="*"/>
    </tx:attributes>
  </tx:advice>
 
  <!-- ensure that the above transactional advice runs for any execution
      of an operation defined by the FooService interface -->
      
  <aop:config>
    <aop:pointcut id="fooServiceOperation" expression="execution(* x.y.service.FooService.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation"/>
  </aop:config>
 
  <!-- don't forget the DataSource -->
  
  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
    <property name="url" value="jdbc:oracle:thin:@rj-t42:1521:elvis"/>
    <property name="username" value="scott"/>
    <property name="password" value="tiger"/>
  </bean>
 
  
  <!-- similarly, don't forget the (particular) PlatformTransactionManager -->
  
  <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
  </bean>
 
  <!-- other <bean/> definitions here -->
  
</beans>
聽鎴戜滑鏉ュ垎鏋愪竴涓嬩笂闈㈢殑閰嶇疆銆傛垜浠鎶婁竴涓湇鍔″璞★紙'fooService' bean锛夊仛鎴愪簨鍔℃€х殑銆傛垜浠兂鏂藉姞鐨勪簨鍔¤涔夊皝瑁呭湪<tx:advice/>瀹氫箟涓€?lt;tx:advice/> 鈥滄妸鎵€鏈変互 'get' 寮€澶寸殑鏂规硶鐪嬪仛鎵ц鍦ㄥ彧璇讳簨鍔′笂涓嬫枃涓紝鍏朵綑鐨勬柟娉曟墽琛屽湪榛樿璇箟鐨勪簨鍔′笂涓嬫枃涓€濄€?鍏朵腑鐨?'transaction-manager' 灞炴€ц璁剧疆涓轰竴涓寚鍚?PlatformTransactionManager bean鐨勫悕瀛楋紙杩欓噷鎸?'txManager'锛夛紝璇ean灏嗗疄闄呬笂瀹炴柦浜嬪姟绠$悊銆?

鎻愮ず

浜嬪疄涓婏紝濡傛灉 PlatformTransactionManager bean鐨勫悕瀛楁槸 'transactionManager' 鐨勮瘽锛屼綘鐨勪簨鍔¢€氱煡锛?lt;tx:advice/>锛変腑鐨?'transaction-manager' 灞炴€у彲浠ュ拷鐣ャ€傚惁鍒欎綘鍒欓渶瑕佸儚涓婁緥閭f牱鏄庣‘鎸囧畾銆?/p>

閰嶇疆涓渶鍚庝竴娈垫槸 <aop:config/> 鐨勫畾涔夛紝瀹冪‘淇濈敱 'txAdvice' bean瀹氫箟鐨勪簨鍔¢€氱煡鍦ㄥ簲鐢ㄤ腑鍚堥€傜殑鐐硅鎵ц銆傞鍏堟垜浠畾涔変簡 涓€涓垏闈紝瀹冨尮閰?FooService 鎺ュ彛瀹氫箟鐨勬墍鏈夋搷浣滐紝鎴戜滑鎶婅鍒囬潰鍙仛 'fooServiceOperation'銆傜劧鍚庢垜浠敤涓€涓€氱煡鍣紙advisor锛夋妸杩欎釜鍒囬潰涓?'txAdvice' 缁戝畾鍦ㄤ竴璧凤紝琛ㄧず褰?'fooServiceOperation' 鎵ц鏃讹紝'txAdvice' 瀹氫箟鐨勯€氱煡閫昏緫灏嗚鎵ц銆?/p>

<aop:pointcut/> 鍏冪礌瀹氫箟鏄疉spectJ鐨勫垏闈㈣〃绀烘硶锛屽彲鍙傝€僑pring 2.0 绗?6 绔?浣跨敤Spring杩涜闈㈠悜鍒囬潰缂栫▼锛圓OP锛夌珷鑾峰緱鏇磋缁嗙殑鍐呭銆?/p>

涓€涓櫘閬嶆€х殑闇€姹傛槸璁╂暣涓湇鍔″眰鎴愪负浜嬪姟鎬х殑銆傛弧瓒宠闇€姹傜殑鏈€濂芥柟寮忔槸璁╁垏闈㈣〃杈惧紡鍖归厤鏈嶅姟灞傜殑鎵€鏈夋搷浣滄柟娉曘€備緥濡傦細

<aop:config>
    <aop:pointcut id="fooServiceMethods" expression="execution(* x.y.service.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceMethods"/>
  </aop:config>

锛堣繖涓緥瀛愪腑鍋囧畾浣犳墍鏈夌殑鏈嶅姟鎺ュ彛瀹氫箟鍦?'x.y.service' 鍖呬腑銆備綘鍚屾牱鍙互鍙傝€?绗?6 绔?浣跨敤Spring杩涜闈㈠悜鍒囬潰缂栫▼锛圓OP锛?绔犺幏寰楁洿璇︾粏鍐呭銆傦級聽

鐜板湪锛屾棦鐒舵垜浠凡缁忓垎鏋愪簡鏁翠釜閰嶇疆锛屼綘鍙兘浼氶棶浜嗭紝鈥滃ソ鍚э紝浣嗘槸鎵€鏈夎繖浜涢厤缃仛浜嗕粈涔堬紵鈥濄€?/p>

涓婇潰鐨勯厤缃皢涓虹敱 'fooService' 瀹氫箟鐨刡ean鍒涘缓涓€涓唬鐞嗗璞★紝杩欎釜浠g悊瀵硅薄琚閰嶄簡浜嬪姟閫氱煡锛屾墍浠ュ綋瀹冪殑鐩稿簲鏂规硶琚皟鐢ㄦ椂锛屼竴涓簨鍔″皢琚惎鍔ㄣ€佹寕璧枫€佽鏍囪涓哄彧璇伙紝鎴栬€呭叾瀹冿紙鏍规嵁璇ユ柟娉曟墍閰嶇疆鐨勪簨鍔¤涔夛級銆?/p>

鎴戜滑鏉ョ湅鐪嬩笅闈㈢殑渚嬪瓙锛屾祴璇曚竴涓嬩笂闈㈢殑閰嶇疆銆?/p>

public final class Boot {

聽 聽 public static void main(final String[] args) throws Exception {

聽 聽 聽 聽 ApplicationContext ctx = new ClassPathXmlApplicationContext("context.xml", Boot.class);

聽 聽 聽 聽 FooService fooService = (FooService) ctx.getBean("fooService");

聽 聽 聽 聽 fooService.insertFoo (new Foo());

聽 聽 }

}

杩愯涓婇潰绋嬪簭鐨勮緭鍑虹粨鏋滅湅璧锋潵鍍忚繖鏍凤紙娉ㄦ剰涓轰簡娓呮璧疯锛孡og4J鐨勬秷鎭拰浠?DefaultFooService 鐨?insertFoo(..) 鏂规硶鎶涘嚭鐨?UnsupportedOperationException 寮傚父鍫嗘爤淇℃伅琚渷鐣ヤ簡锛夈€?/p>

聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 <!-- Spring瀹瑰櫒寮€濮嬪惎鍔?.. -->

聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽聽

[AspectJInvocationContextExposingAdvisorAutoProxyCreator] - Creating implicit proxy

聽 聽 聽 聽 for bean 'fooService' with 0 common interceptors and 1 specific interceptors

聽 聽 <!-- the DefaultFooService is actually proxied -->

聽 聽聽

[JdkDynamicAopProxy] - Creating JDK dynamic proxy for [x.y.service.DefaultFooService]

聽 聽 <!-- ... the insertFoo(..) method is now being invoked on the proxy -->

聽 聽聽

[TransactionInterceptor] - Getting transaction for x.y.service.FooService.insertFoo

聽 聽 <!-- the transactional advice kicks in here... -->

聽 聽聽

[DataSourceTransactionManager] - Creating new transaction with name [x.y.service.FooService.insertFoo]

[DataSourceTransactionManager] - Acquired Connection

聽 聽 聽 聽 [org.apache.commons.dbcp.PoolableConnection@a53de4] for JDBC transaction

聽 聽 <!-- the insertFoo(..) method from DefaultFooService throws an exception... -->

聽 聽聽

[RuleBasedTransactionAttribute] - Applying rules to determine whether transaction should

聽 聽 聽 聽 rollback on java.lang.UnsupportedOperationException

[TransactionInterceptor] - Invoking rollback for transaction on x.y.service.FooService.insertFoo

聽 聽 聽 聽 due to throwable [java.lang.UnsupportedOperationException]

聽 聽<!-- and the transaction is rolled back (by default, RuntimeException instances cause rollback) -->

聽 聽

[DataSourceTransactionManager] - Rolling back JDBC transaction on Connection

聽 聽 聽 聽 [org.apache.commons.dbcp.PoolableConnection@a53de4]

[DataSourceTransactionManager] - Releasing JDBC Connection after transaction

[DataSourceUtils] - Returning JDBC Connection to DataSource

Exception in thread "main" java.lang.UnsupportedOperationException

聽 聽 聽 聽 at x.y.service.DefaultFooService.insertFoo(DefaultFooService.java:14)

聽 聽<!-- AOP infrastructure stack trace elements removed for clarity -->

聽 聽

聽 聽 聽 聽 at $Proxy0.insertFoo(Unknown Source)

聽 聽 聽 聽 at Boot.main(Boot.java:11)

9.5.3. 鍥炴粴

鍦ㄥ墠闈㈢殑绔犺妭閲岋紝姒傝堪浜嗗浣曞湪浣犵殑搴旂敤閲屼负绫荤壒鍒槸鏈嶅姟灞傜殑绫绘寚瀹氫簨鍔℃€х殑鍩烘湰鏂规硶銆傝繖涓€绔犲皢鎻忚堪鍦ㄤ竴涓畝鍗曠殑澹版槑寮忛厤缃腑濡備綍浣犳墠鑳芥帶鍒朵簨鍔$殑鍥炴粴銆?/p>

涓€涓鏄撶殑锛堝拰琚帹鑽愮殑锛夋柟娉曟槸鍦⊿pring妗嗘灦鐨勪簨鍔℃灦鏋勯噷鎸囧嚭褰揷ontext鐨勪簨鍔¢噷鐨勪唬鐮佹姏鍑?Exception 鏃朵簨鍔¤繘琛屽洖婊氥€係pring妗嗘灦鐨勪簨鍔″熀纭€鏋舵瀯浠g爜灏嗕粠璋冪敤鐨勫爢鏍堥噷鎹曡幏鍒颁换浣曟湭澶勭悊鐨?Exception锛屽苟灏嗘爣璇嗕簨鍔″皢鍥炴粴銆偮?/p>

鐒惰€岋紝璇锋敞鎰廠pring妗嗘灦鐨勪簨鍔″熀纭€鏋舵瀯浠g爜灏嗛粯璁ゅ湴 鍙?鍦ㄦ姏鍑鸿繍琛屾椂鍜寀nchecked exceptions鏃舵墠鏍囪瘑浜嬪姟鍥炴粴銆?涔熷氨鏄锛屽綋鎶涘嚭涓€涓?RuntimeException 鎴栧叾瀛愮被渚嬬殑瀹炰緥鏃躲€傦紙Errors 涔熶竴鏍?- 榛樿鍦?- 鏍囪瘑浜嬪姟鍥炴粴銆傦級浠庝簨鍔℃柟娉曚腑鎶涘嚭鐨凜hecked exceptions灏?涓?琚爣璇嗚繘琛屼簨鍔″洖婊氥€偮?/p>

灏辨槸杩欎簺榛樿鐨勮缃紱涓ユ牸瑙勫畾浜嗗摢浜?Exception 绫诲瀷灏嗚鏍囪瘑杩涜浜嬪姟鍥炴粴銆?涓嬮潰鐨刋ML閰嶇疆鐗囨柇閲岀ず鑼冧簡濡備綍閰嶇疆涓€涓猚hecked锛屽簲鐢ㄧ▼搴忔寚瀹氱殑 Exception 绫诲瀷鏉ユ爣璇嗕簨鍔″洖婊氥€偮?/p>

<tx:advice id="txAdvice" transaction-manager="txManager">
  <tx:attributes>
         <tx:method name="get*" read-only="false" rollback-for="NoProductInStockException"/>
         <tx:method name="*"/>
  </tx:attributes>
</tx:advice>

绗簩鏂规硶鏄湪Spring妗嗘灦鐨勪簨鍔℃灦鏋勯噷閫氳繃 缂栫▼寮?鏂瑰紡鎸囧嚭涓€涓簨鍔″皢琚洖婊氥€?铏界劧杩欎釜闈炲父绠€鍗曪紝浣嗘槸杩欎釜鏂规硶瀵逛簬Spring妗嗘灦鐨勪簨鍔℃灦鏋勬潵璇达紝鍦ㄤ綘鐨勪唬鐮佹槸楂樺叆渚电殑鍜岀揣钘曞悎鐨?涓嬮潰鐨勪唬鐮佺墖鏂噷绀鸿寖浜哠pring妗嗘灦绠$悊浜嬪姟鐨勭紪绋嬪紡鍥炴粴锛毬?/p>

public void resolvePosition() {
    try {
        // some business logic...
    } catch (NoProductInStockException ex) {
        // trigger rollback programmatically
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }
}

寮虹儓鎺ㄨ崘浣犲敖鍙兘鍦颁娇鐢ㄥ0鏄庡紡浜嬪姟鍥炴粴鏂规硶銆?缂栫▼寮忔柟娉曠殑鍥炴粴瀵逛綘鏉ヨ鏄彲瑙侊紝濡傛灉浣犻渶瑕佸畠浣犲氨鍙互浣跨敤锛屼絾鏄娇鐢ㄥ畠灏辩洿鎺ヨ繚鍙嶄簡鍦ㄤ綘鐨勫簲鐢ㄤ腑浣跨敤涓€涓函鍩轰簬POJO鐨勬ā鍨嬨€偮?/p>

9.5.4. 涓轰笉鍚岀殑bean閰嶇疆涓嶅悓鐨勪簨鍔¤涔?/p>

鐜板湪鎴戜滑鑰冭檻涓€涓嬭繖鏍风殑鍦烘櫙锛屼綘鏈夎澶氭湇鍔″璞★紝鑰屼笖鎯充负涓嶅悓缁勭殑瀵硅薄璁剧疆 瀹屽叏涓嶅悓 鐨勪簨鍔¤涔夈€傚湪Spring涓紝浣犲彲浠ラ€氳繃瀹氫箟鍚勮嚜鐗瑰畾鐨?<aop:advisor/> 鍏冪礌锛屾瘡涓猘dvisor閲囩敤涓嶅悓鐨?'pointcut' 鍜?'advice-ref' 灞炴€э紝鏉ヨ揪鍒扮洰鐨勩€?/p>

鍊熷姪浜庝竴涓緥瀛愶紝鎴戜滑鍋囧畾浣犳墍鏈夌殑鏈嶅姟灞傜被瀹氫箟鍦ㄤ互 'x.y.service' 涓烘牴鐨勫寘鍐呫€備负浜嗚service鍖咃紙鎴栧瓙鍖咃級涓嬫墍鏈夊悕瀛椾互 'Service' 缁撳熬鐨勭被鐨勫璞℃嫢鏈夐粯璁ょ殑浜嬪姟璇箟锛屼綘鍙互閰嶇疆濡備笅锛?/p>

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
 
<aop:config>
 
    <aop:pointcut id="serviceOperation" expression="execution(* x.y.service..*Service.*(..))"/>
 
        <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice"/>
 
</aop:config>
 
<!-- these two beans will be transactional... -->
 
<bean id="fooService" class="x.y.service.DefaultFooService"/>
<bean id="barService" class="x.y.service.extras.SimpleBarService"/>
 
<!-- ...and these two beans won't -->
 
    <bean id="anotherService" class="org.xyz.SomeService"/> <!-- (not in the right package) -->
    <bean id="barManager" class="x.y.service.SimpleBarManager"/> <!-- (doesn't end in 'Service') -->
 
    <tx:advice id="txAdvice">
        <tx:attributes>
            <tx:method name="get*" read-only="true"/>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>
 
    <!-- other transaction infrastructure beans such as a PlatformTransactionManager omitted... -->
 

</beans>

涓嬮潰鐨勯厤缃ず渚嬫紨绀轰簡涓や釜涓嶅悓鐨刡ean鎷ユ湁瀹屽叏涓嶅悓鐨勪簨鍔¢厤缃€偮?/p>

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
 
    <aop:config>
 
        <aop:pointcut id="defaultServiceOperation" expression="execution(* x.y.service.*Service.*(..))"/>
        <aop:advisor pointcut-ref="defaultServiceOperation" advice-ref="defaultTxAdvice"/>
        
        <aop:pointcut id="noTxServiceOperation" expression="execution(* x.y.service.ddl.DefaultDdlManager.*(..))"/>
        <aop:advisor pointcut-ref="noTxServiceOperation" advice-ref="noTxAdvice"/>
 
    </aop:config>
 
    <!-- this bean will be transactional (c.f. the 'defaultServiceOperation' pointcut) -->
    <bean id="fooService" class="x.y.service.DefaultFooService"/>
 
    <!-- this bean will also be transactional, but with totally different transactional settings -->
    <bean id="anotherFooService" class="x.y.service.ddl.DefaultDdlManager"/>
 
    <tx:advice id="defaultTxAdvice">
        <tx:attributes>
            <tx:method name="get*" read-only="true"/>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>
    
    <tx:advice id="noTxAdvice">
        <tx:attributes>
            <tx:method name="*" propagation="NEVER"/>
        </tx:attributes>
    </tx:advice>
 
    <!-- other transaction infrastructure beans such as a PlatformTransactionManager omitted... -->

</beans>

9.5.5. <tx:advice/> 鏈夊叧鐨勮缃?/p>

杩欎竴鑺傞噷灏嗘弿杩伴€氳繃 <tx:advice/> 鏍囩鏉ユ寚瀹氫笉鍚岀殑浜嬪姟鎬ц缃€傞粯璁ょ殑 <tx:advice/> 璁剧疆濡備笅锛毬?/p>

浜嬪姟浼犳挱璁剧疆鏄?REQUIRED

闅旂绾у埆鏄?DEFAULT

浜嬪姟鏄?璇?鍐?/p>

浜嬪姟瓒呮椂榛樿鏄緷璧栦簬浜嬪姟绯荤粺鐨勶紝鎴栬€呬簨鍔¤秴鏃舵病鏈夎鏀寔銆?/p>

浠讳綍 RuntimeException 灏嗚Е鍙戜簨鍔″洖婊氾紝浣嗘槸浠讳綍 checked Exception 灏嗕笉瑙﹀彂浜嬪姟鍥炴粴

杩欎簺榛樿鐨勮缃綋鐒朵篃鏄彲浠ヨ鏀瑰彉鐨勩€?<tx:advice/> 鍜?<tx:attributes/> 鏍囩閲岀殑 <tx:method/> 鍚勭灞炴€ц缃€荤粨濡備笅锛毬?/p>

琛?9.1. <tx:method/> 鏈夊叧鐨勮缃?/p>

灞炴€?鏄惁闇€瑕侊紵 榛樿鍊?鎻忚堪 
name 鏄?  涓庝簨鍔″睘鎬у叧鑱旂殑鏂规硶鍚嶃€傞€氶厤绗︼紙*锛夊彲浠ョ敤鏉ユ寚瀹氫竴鎵瑰叧鑱斿埌鐩稿悓鐨勪簨鍔″睘鎬х殑鏂规硶銆?濡傦細'get*'銆?handle*'銆?on*Event'绛夌瓑銆?
 
propagation 涓?REQUIRED 浜嬪姟浼犳挱琛屼负 
isolation 涓?DEFAULT 浜嬪姟闅旂绾у埆 
timeout 涓?-1 浜嬪姟瓒呮椂鐨勬椂闂达紙浠ョ涓哄崟浣嶏級 
read-only 涓?false 浜嬪姟鏄惁鍙锛?
rollback-for 涓?  灏嗚瑙﹀彂杩涜鍥炴粴鐨?Exception(s)锛涗互閫楀彿鍒嗗紑銆?濡傦細'com.foo.MyBusinessException,ServletException' 
 
no-rollback-for 涓?  涓?琚Е鍙戣繘琛屽洖婊氱殑 Exception(s)锛涗互閫楀彿鍒嗗紑銆?濡傦細'com.foo.MyBusinessException,ServletException' 
 

9.5.6. 浣跨敤 @Transactional

娉ㄦ剰

@Transactional 娉ㄨВ鍙婂叾鏀寔绫绘墍鎻愪緵鐨勫姛鑳芥渶浣庤姹備娇鐢↗ava 5锛圱iger锛夈€偮?/p>

闄や簡鍩轰簬XML鏂囦欢鐨勫0鏄庡紡浜嬪姟閰嶇疆澶栵紝浣犱篃鍙互閲囩敤鍩轰簬娉ㄨВ寮忕殑浜嬪姟閰嶇疆鏂规硶銆傜洿鎺ュ湪Java婧愪唬鐮佷腑澹版槑浜嬪姟璇箟鐨勫仛娉曡浜嬪姟澹版槑鍜屽皢鍙楀叾褰卞搷鐨勪唬鐮佽窛绂绘洿杩戜簡锛岃€屼笖涓€鑸潵璇翠笉浼氭湁涓嶆伆褰撶殑鑰﹀悎鐨勯闄╋紝鍥犱负锛屼娇鐢ㄤ簨鍔℃€х殑浠g爜鍑犱箮鎬绘槸琚儴缃插湪浜嬪姟鐜涓€偮?/p>

涓嬮潰鐨勪緥瀛愬緢濂藉湴婕旂ず浜?@Transactional 娉ㄨВ鐨勬槗鐢ㄦ€э紝闅忓悗瑙i噴鍏朵腑鐨勭粏鑺傘€傚厛鐪嬬湅鍏朵腑鐨勭被瀹氫箟锛?/p>

<!-- the service class that we want to make transactional -->
@Transactional
public class DefaultFooService implements FooService {
    Foo getFoo(String fooName);
    Foo getFoo(String fooName, String barName);
    void insertFoo(Foo foo);
    void updateFoo(Foo foo);
}

褰撲笂杩扮殑POJO瀹氫箟鍦⊿pring IoC瀹瑰櫒閲屾椂锛屼笂杩癰ean瀹炰緥浠呬粎閫氳繃涓€ 琛寈ml閰嶇疆灏卞彲浠ヤ娇瀹冨叿鏈変簨鍔℃€х殑銆傚涓嬶細

 <!-- from the file 'context.xml' -->
          
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
 
  <!-- this is the service object that we want to make transactional -->
  <bean id="fooService" class="x.y.service.DefaultFooService"/>
 
  <!-- enable the configuration of transactional behavior based on annotations -->
  <tx:annotation-driven transaction-manager="txManager"/>
 
  <!-- a PlatformTransactionManager is still required -->
  <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!-- (this dependency is defined somewhere else) -->
    <property name="dataSource" ref="dataSource"/>
  </bean>
 
  <!-- other <bean/> definitions here -->

</beans>

鎻愮ず

瀹為檯涓婏紝濡傛灉浣犵敤 'transactionManager' 鏉ュ畾涔?PlatformTransactionManager bean鐨勫悕瀛楃殑璇濓紝浣犲氨鍙互蹇界暐 <tx:annotation-driven/> 鏍囩閲岀殑 'transaction-manager' 灞炴€с€?濡傛灉 PlatformTransactionManager bean浣犺閫氳繃鍏跺畠鍚嶇О鏉ユ敞鍏ョ殑璇濓紝浣犲繀椤荤敤 'transaction-manager' 灞炴€ф潵鎸囧畾瀹冿紝濡備笂鎵€绀恒€偮?/p>

鏂规硶鐨勫彲瑙佸害鍜?@Transactional

@Transactional 娉ㄨВ搴旇鍙搴旂敤鍒?public 鍙搴︾殑鏂规硶涓娿€?濡傛灉浣犲湪 protected銆乸rivate 鎴栬€?package-visible 鐨勬柟娉曚笂浣跨敤 @Transactional 娉ㄨВ锛屽畠涔熶笉浼氭姤閿欙紝 浣嗘槸杩欎釜琚敞瑙g殑鏂规硶灏嗕笉浼氬睍绀哄凡閰嶇疆鐨勪簨鍔¤缃€偮?/p>

@Transactional 娉ㄨВ鍙互琚簲鐢ㄤ簬鎺ュ彛瀹氫箟鍜屾帴鍙f柟娉曘€佺被瀹氫箟鍜岀被鐨?public 鏂规硶涓娿€傜劧鑰岋紝璇锋敞鎰忎粎浠?@Transactional 娉ㄨВ鐨勫嚭鐜颁笉瓒充簬寮€鍚簨鍔¤涓猴紝瀹冧粎浠?鏄竴绉嶅厓鏁版嵁锛岃兘澶熻鍙互璇嗗埆 @Transactional 娉ㄨВ鍜屼笂杩扮殑閰嶇疆閫傚綋鐨勫叿鏈変簨鍔¤涓虹殑beans鎵€浣跨敤銆備笂闈㈢殑渚嬪瓙涓紝鍏跺疄姝f槸 <tx:annotation-driven/>鍏冪礌鐨勫嚭鐜?寮€鍚?浜嗕簨鍔¤涓恒€?/p>

Spring鍥㈤槦鐨勫缓璁槸浣犲湪鍏蜂綋鐨勭被锛堟垨绫荤殑鏂规硶锛変笂浣跨敤 @Transactional 娉ㄨВ锛岃€屼笉瑕佷娇鐢ㄥ湪绫绘墍瑕佸疄鐜扮殑浠讳綍鎺ュ彛涓娿€備綘褰撶劧鍙互鍦ㄦ帴鍙d笂浣跨敤 @Transactional 娉ㄨВ锛屼絾鏄繖灏嗗彧鑳藉綋浣犺缃簡鍩轰簬鎺ュ彛鐨勪唬鐞嗘椂瀹冩墠鐢熸晥銆傚洜涓烘敞瑙f槸 涓嶈兘缁ф壙 鐨勶紝杩欏氨鎰忓懗鐫€濡傛灉浣犳鍦ㄤ娇鐢ㄥ熀浜庣被鐨勪唬鐞嗘椂锛岄偅涔堜簨鍔$殑璁剧疆灏嗕笉鑳借鍩轰簬绫荤殑浠g悊鎵€璇嗗埆锛岃€屼笖瀵硅薄涔熷皢涓嶄細琚簨鍔′唬鐞嗘墍鍖呰锛堝皢琚‘璁や负涓ラ噸鐨勶級銆傚洜姝わ紝璇锋帴鍙桽pring鍥㈤槦鐨勫缓璁苟涓斿湪鍏蜂綋鐨勭被涓婁娇鐢?@Transactional 娉ㄨВ銆偮?/p>

娉ㄦ剰

褰撲娇鐢?@Transactional 椋庢牸鐨勮繘琛屽0鏄庡紡浜嬪姟瀹氫箟鏃讹紝浣犲彲浠ラ€氳繃 <tx:annotation-driven/> 鍏冪礌鐨?"proxy-target-class" 灞炴€у€兼潵鎺у埗鏄熀浜庢帴鍙g殑杩樻槸鍩轰簬绫荤殑浠g悊琚垱寤恒€傚鏋?"proxy-target-class" 灞炲€艰璁剧疆涓?"true"锛岄偅涔堝熀浜庣被鐨勪唬鐞嗗皢璧蜂綔鐢紙杩欐椂闇€瑕丆GLIB搴揷glib.jar鍦–LASSPATH涓級銆傚鏋?"proxy-target-class" 灞炲€艰璁剧疆涓?"false" 鎴栬€呰繖涓睘鎬ц鐪佺暐锛岄偅涔堟爣鍑嗙殑JDK鍩轰簬鎺ュ彛鐨勪唬鐞嗗皢璧蜂綔鐢ㄣ€偮?/p>

鍦ㄥ鏁版儏褰笅锛屾柟娉曠殑浜嬪姟璁剧疆灏嗚浼樺厛鎵ц銆傚湪涓嬪垪鎯呭喌涓嬶紝渚嬪锛?DefaultFooService 绫昏娉ㄨВ涓哄彧璇讳簨鍔★紝浣嗘槸锛岃繖涓被涓殑 updateFoo(Foo) 鏂规硶鐨?@Transactional 娉ㄨВ鐨勪簨鍔¤缃皢浼樺厛浜庣被绾у埆娉ㄨВ鐨勪簨鍔¤缃€偮?/p>

@Transactional(readOnly = true)
public class DefaultFooService implements FooService {
    public Foo getFoo(String fooName) {
        // do something
    }
    // these settings have precedence for this method
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    public void updateFoo(Foo foo) {
        // do something   
    }
}

9.5.6.1. @Transactional 鏈夊叧鐨勮缃?/p>

@Transactional 娉ㄨВ鏄敤鏉ユ寚瀹氭帴鍙c€佺被鎴栨柟娉曞繀椤绘嫢鏈変簨鍔¤涔夌殑鍏冩暟鎹€?濡傦細鈥滃綋涓€涓柟娉曞紑濮嬭皟鐢ㄦ椂灏卞紑鍚竴涓柊鐨勫彧璇讳簨鍔★紝骞跺仠姝㈡帀浠讳綍鐜板瓨鐨勪簨鍔♀€濄€?榛樿鐨?@Transactional 璁剧疆濡備笅锛毬?/p>

浜嬪姟浼犳挱璁剧疆鏄?PROPAGATION_REQUIRED

浜嬪姟闅旂绾у埆鏄?ISOLATION_DEFAULT

浜嬪姟鏄?璇?鍐?/p>

浜嬪姟瓒呮椂榛樿鏄緷璧栦簬浜嬪姟绯荤粺鐨勶紝鎴栬€呬簨鍔¤秴鏃舵病鏈夎鏀寔銆?/p>

浠讳綍 RuntimeException 灏嗚Е鍙戜簨鍔″洖婊氾紝浣嗘槸浠讳綍 checked Exception 灏嗕笉瑙﹀彂浜嬪姟鍥炴粴

杩欎簺榛樿鐨勮缃綋鐒朵篃鏄彲浠ヨ鏀瑰彉鐨勩€?@Transactional 娉ㄨВ鐨勫悇绉嶅睘鎬ц缃€荤粨濡備笅锛毬?/p>

琛?9.2. @Transactional 娉ㄨВ鐨勫睘鎬?/p>

灞炴€?绫诲瀷 鎻忚堪聽

浼犳挱鎬?鏋氫妇鍨嬶細Propagation 聽鍙€夌殑浼犳挱鎬ц缃?/p>

闅旂鎬?鏋氫妇鍨嬶細Isolation 聽鍙€夌殑闅旂鎬х骇鍒紙榛樿鍊硷細ISOLATION_DEFAULT锛壜?/p>

鍙鎬?甯冨皵鍨?璇诲啓鍨嬩簨鍔?vs. 鍙鍨嬩簨鍔÷?/p>

瓒呮椂 int鍨嬶紙浠ョ涓哄崟浣嶏級 浜嬪姟瓒呮椂聽

鍥炴粴寮傚父绫伙紙rollbackFor锛?涓€缁?Class 绫荤殑瀹炰緥锛屽繀椤绘槸Throwable 鐨勫瓙绫?涓€缁勫紓甯哥被锛岄亣鍒版椂 蹇呴』 杩涜鍥炴粴銆傞粯璁ゆ儏鍐典笅checked exceptions涓嶈繘琛屽洖婊氾紝浠卽nchecked exceptions锛堝嵆RuntimeException鐨勫瓙绫伙級鎵嶈繘琛屼簨鍔″洖婊氥€偮?/p>

鍥炴粴寮傚父绫诲悕锛坮ollbackForClassname锛?涓€缁?Class 绫荤殑鍚嶅瓧锛屽繀椤绘槸Throwable鐨勫瓙绫?涓€缁勫紓甯哥被鍚嶏紝閬囧埌鏃?蹇呴』 杩涜鍥炴粴聽

涓嶅洖婊氬紓甯哥被锛坣oRollbackFor锛?涓€缁?Class 绫荤殑瀹炰緥锛屽繀椤绘槸Throwable 鐨勫瓙绫?涓€缁勫紓甯哥被锛岄亣鍒版椂 蹇呴』涓?鍥炴粴銆偮?/p>

涓嶅洖婊氬紓甯哥被鍚嶏紙noRollbackForClassname锛?涓€缁?Class 绫荤殑鍚嶅瓧锛屽繀椤绘槸Throwable 鐨勫瓙绫?涓€缁勫紓甯哥被锛岄亣鍒版椂 蹇呴』涓?鍥炴粴聽

9.5.7. 鎻掑叆浜嬪姟鎿嶄綔

鑰冭檻杩欐牱鐨勬儏鍐碉紝浣犳湁涓€涓被鐨勫疄渚嬶紝鑰屼笖甯屾湜 鍚屾椂鎻掑叆浜嬪姟鎬ч€氱煡锛坅dvice锛夊拰涓€浜涚畝鍗曠殑鍓栨瀽锛坧rofiling锛夐€氱煡銆傞偅涔堬紝鍦?lt;tx:annotation-driven/>鐜涓鎬庝箞鍋氾紵

鎴戜滑璋冪敤 updateFoo(Foo) 鏂规硶鏃跺笇鏈涜繖鏍凤細

閰嶇疆鐨勫墫鏋愬垏闈紙profiling aspect锛夊紑濮嬪惎鍔紝

鐒跺悗杩涘叆浜嬪姟閫氱煡锛堟牴鎹厤缃垱寤轰竴涓柊浜嬪姟鎴栧姞鍏ヤ竴涓凡缁忓瓨鍦ㄧ殑浜嬪姟锛夛紝

鐒跺悗鎵ц鍘熷瀵硅薄鐨勬柟娉曪紝

鐒跺悗浜嬪姟鎻愪氦锛堟垜浠亣瀹氳繖閲屼竴鍒囨甯革級锛?/p>

鏈€鍚庡墫鏋愬垏闈㈡姤鍛婃暣涓簨鍔℃柟娉曟墽琛岃繃绋嬭姳浜嗗灏戞椂闂淬€?/p>

娉ㄦ剰

杩欑珷涓嶆槸涓撻棬璁茶堪AOP鐨勪换浣曠粏鑺傦紙闄や簡搴旂敤浜庝簨鍔℃柟闈㈢殑涔嬪锛夈€傝鍙傝€?绗?6 绔?浣跨敤Spring杩涜闈㈠悜鍒囬潰缂栫▼锛圓OP锛?绔犱互鑾峰緱瀵瑰悇绉岮OP閰嶇疆鍙婂叾涓€鑸蹇电殑璇︾粏鍙欒堪銆偮?/p>

杩欓噷鏈変竴浠界畝鍗曠殑鍓栨瀽鍒囬潰锛坧rofiling aspect锛夌殑浠g爜銆傦紙娉ㄦ剰锛岄€氱煡鐨勯『搴忔槸鐢?Ordered 鎺ュ彛鏉ユ帶鍒剁殑銆傝鎯充簡瑙f洿澶氱粏鑺傦紝璇峰弬鑰?绗?6.2.4.7 鑺?鈥滈€氱煡锛圓dvice锛夐『搴忊€?鑺傘€傦級聽

package x.y;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.util.StopWatch;
import org.springframework.core.Ordered;
 
public class SimpleProfiler implements Ordered {
 
    private int order;
    // allows us to control the ordering of advice
    public int getOrder() {
        return this.order;
    }
    public void setOrder(int order) {
        this.order = order;
    }
    // this method is the around advice
    public Object profile(ProceedingJoinPoint call) throws Throwable {
        Object returnValue;
        StopWatch clock = new StopWatch(getClass().getName());
        try {
            clock.start(call.toShortString());
            returnValue = call.proceed();
        } finally {
            clock.stop();
            System.out.println(clock.prettyPrint());
        }
        return returnValue;
    }
}
 

杩欓噷鏄府鍔╂弧瓒虫垜浠笂杩拌姹傜殑閰嶇疆鏁版嵁銆偮?/p>

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="
   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
   http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
 
    <bean id="fooService" class="x.y.service.DefaultFooService"/>
 
    <!-- this is the aspect -->
    <bean id="profiler" class="x.y.SimpleProfiler">
        <!-- execute before the transactional advice (hence the lower order number) -->
        
        <property name="order" value="1"/>
    </bean>
    
    <tx:annotation-driven transaction-manager="txManager"/>
 
    <aop:config>
        <!-- this advice will execute around the transactional advice -->
        <aop:aspect id="profilingAspect" ref="profiler">
            <aop:pointcut id="serviceMethodWithReturnValue" expression="execution(!void x.y..*Service.*(..))"/>
            <aop:around method="profile" pointcut-ref="serviceMethodWithReturnValue"/>
        </aop:aspect>
    </aop:config>
 
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
        <property name="url" value="jdbc:oracle:thin:@rj-t42:1521:elvis"/>
        <property name="username" value="scott"/>
        <property name="password" value="tiger"/>
    </bean>
 
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
 
</beans>

涓婇潰閰嶇疆鐨勭粨鏋滃皢鑾峰緱鍒颁竴涓嫢鏈夊墫鏋愬拰浜嬪姟鏂归潰鐨?鎸夐偅鏍风殑椤哄簭 搴旂敤浜庡畠涓婇潰鐨?'fooService' bean銆?璁稿闄勫姞鐨勬柟闈㈢殑閰嶇疆灏嗕竴璧疯揪鍒拌繖鏍风殑鏁堟灉銆偮?/p>

鏈€鍚庯紝涓嬮潰鐨勪竴浜涚ず渚嬫紨绀轰簡浣跨敤绾疿ML澹版槑鐨勬柟娉曟潵杈惧埌涓婇潰涓€鏍风殑璁剧疆鏁堟灉銆偮?/p>

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
   http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
 
    <bean id="fooService" class="x.y.service.DefaultFooService"/>
    <!-- the profiling advice -->
    <bean id="profiler" class="x.y.SimpleProfiler">
        <!-- execute before the transactional advice (hence the lower order number) -->
        <property name="order" value="1"/>
    </bean>
 
    <aop:config>
        <aop:pointcut id="entryPointMethod" expression="execution(* x.y..*Service.*(..))"/>
        <!-- will execute after the profiling advice (c.f. the order attribute) -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="entryPointMethod"order="2"/> 
        <!-- order value is higher than the profiling aspect -->
        <aop:aspect id="profilingAspect" ref="profiler">
            <aop:pointcut id="serviceMethodWithReturnValue" expression="execution(!void x.y..*Service.*(..))"/>
            <aop:around method="profile" pointcut-ref="serviceMethodWithReturnValue"/>
        </aop:aspect>
    </aop:config>
 
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="get*" read-only="true"/>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>
    <!-- other <bean/> definitions such as a DataSource and a PlatformTransactionManager here -->
</beans>

涓婇潰閰嶇疆鐨勭粨鏋滄槸鍒涘缓浜嗕竴涓?'fooService' bean锛屽墫鏋愭柟闈㈠拰浜嬪姟鏂归潰琚?渚濈収椤哄簭 鏂藉姞鍏朵笂銆傚鏋滄垜浠笇鏈涘墫鏋愰€氱煡鍦ㄧ洰鏍囨柟娉曟墽琛屼箣鍓?鍚庝簬 浜嬪姟閫氱煡鎵ц锛岃€屼笖鍦ㄧ洰鏍囨柟娉曟墽琛屼箣鍚?鍏堜簬 浜嬪姟閫氱煡锛屾垜浠彲浠ョ畝鍗曞湴浜ゆ崲涓や釜閫氱煡bean鐨刼rder鍊笺€?/p>

濡傛灉閰嶇疆涓寘鍚洿澶氱殑鏂归潰锛屽畠浠皢浠ュ悓鏍风殑鏂瑰紡鍙楀埌褰卞搷銆?/p>

9.5.8. 缁撳悎AspectJ浣跨敤 @Transactional

閫氳繃AspectJ鍒囬潰锛屼綘涔熷彲浠ュ湪Spring瀹瑰櫒涔嬪浣跨敤Spring妗嗘灦鐨?@Transactional 鍔熻兘銆傝浣跨敤杩欓」鍔熻兘浣犲繀椤诲厛缁欑浉搴旂殑绫诲拰鏂规硶鍔犱笂 @Transactional娉ㄨВ锛岀劧鍚庢妸 spring-aspects.jar 鏂囦欢涓畾涔夌殑 org.springframework.transaction.aspectj.AnnotationTransactionAspect 鍒囬潰杩炴帴杩涳紙缁囧叆锛変綘鐨勫簲鐢ㄣ€傚悓鏍凤紝璇ュ垏闈㈠繀椤婚厤缃竴涓簨鍔$鐞嗗櫒銆備綘褰撶劧鍙互閫氳繃Spring妗嗘灦瀹瑰櫒鏉ュ鐞嗘敞鍏ワ紝浣嗗洜涓烘垜浠繖閲屽叧娉ㄤ簬鍦⊿pring瀹瑰櫒涔嬪杩愯搴旂敤锛屾垜浠皢鍚戜綘灞曠ず濡備綍閫氳繃鎵嬪姩涔﹀啓浠g爜鏉ュ畬鎴愩€?/p>

娉ㄦ剰

鍦ㄦ垜浠户缁箣鍓嶏紝浣犲彲鑳介渶瑕佸ソ濂借涓€涓嬪墠闈㈢殑绗?9.5.6 鑺?鈥滀娇鐢?@Transactional鈥?鍜?绗?6 绔?浣跨敤Spring杩涜闈㈠悜鍒囬潰缂栫▼锛圓OP锛?涓ょ珷銆?/p>

// construct an appropriate transaction manager聽

DataSourceTransactionManager txManager = new DataSourceTransactionManager(getDataSource());

// configure the AnnotationTransactionAspect to use it; this must be done before executing any transactional methods

AnnotationTransactionAspect.aspectOf().setTransactionManager (txManager);聽

娉ㄦ剰

浣跨敤姝ゅ垏闈紙aspect锛夛紝浣犲繀椤诲湪 瀹炵幇 绫伙紙鍜?鎴栫被閲岀殑鏂规硶锛夈€佽€?涓嶆槸 绫荤殑浠讳綍鎵€瀹炵幇鐨勬帴鍙d笂闈㈣繘琛屾敞瑙c€侫spectJ閬靛惊Java鐨勬帴鍙d笂鐨勬敞瑙?涓嶈缁ф壙 鐨勮鍒欍€偮?/p>

绫讳笂鐨?@Transactional 娉ㄨВ鎸囧畾浜嗙被閲岀殑浠讳綍 public 鏂规硶鎵ц鐨勯粯璁や簨鍔¤涔夈€偮?/p>

绫婚噷鐨勬柟娉曠殑 @Transactional 灏嗚鐩栨帀绫绘敞瑙g殑榛樿浜嬪姟璇箟锛堝浣曞瓨鍦ㄧ殑璇濓級銆?public銆乸rotected鍜岄粯璁ゅ彲瑙佺殑鏂规硶鍙兘閮借娉ㄨВ銆傜洿鎺ュ protected鍜岄粯璁ゅ彲瑙佺殑鏂规硶杩涜娉ㄨВ锛岃杩欎簺鏂规硶鍦ㄦ墽琛屾椂鍘昏幏鍙栨墍瀹氫箟鐨勪簨鍔″垝鍒嗘槸鍞竴鐨勯€斿緞銆偮?/p>

瑕佹妸 AnnotationTransactionAspect 缁囧叆浣犵殑搴旂敤锛屼綘鎴栬€呭熀浜嶢spectJ鏋勫缓浣犵殑搴旂敤锛堝弬鑰?AspectJ Development Guide锛夛紝鎴栬€呴噰鍙栤€滆浇鍏ユ椂缁囧叆鈥濓紙load-time weaving锛夛紝鍙傝€?绗?6.8.4 鑺?鈥滃湪Spring搴旂敤涓娇鐢ˋspectJ Load-time weaving锛圠TW锛夆€?鑾峰緱鍏充簬浣跨敤AspectJ杩涜鈥滆浇鍏ユ椂缁囧叆鈥濈殑璁ㄨ銆?/p>