spring知識點分析之aop

一、介紹

Spring對面向切面編程提供了強有力的支持,通過它讓我們將業務邏輯從應用服務(事務管理)中分離出來,實現

了高內聚開發,應用對象只關注業務邏輯,不再負責其他系統問題(如日誌、事務、權限控制),Spring支持用戶自定義切面。

面向切面編程完善spring的依賴注入,面向切面編程在spring中主要表現在兩個方面:

1.面向切面編程提供聲明式事務管理

2.spring支持用戶自定義的切面

面向切面編程是對面向對象編程的補充,面向對象編程將程序分解成各個層次的對象,面向切面編程將程序運行

過程分解成各個切面。aop從程序運行角度考慮程序的結構,提取業務處理過程的切面,oop是靜態的抽象,aop

是動態的抽象,是對應用執行過程中的步驟進行抽象,從而獲得步驟之間的邏輯劃分。通俗地講,它相當於一個

攔截器,攔截一些過程,例如,當一個方法執行,spring aop可以劫持一個執行的方法,在方法執行之前或之後

添加額外的功能。

1.特點

   優點:①各個步驟之間的良好隔離性

              ②源代碼無關性

              ③把次要問題代碼放在一個統一的地方,而不是在基本業務邏輯中

AOP核心概念

1、橫切關注點

對哪些方法進行攔截,攔截後怎麼處理,這些關注點稱之爲橫切關注點

2、切面(aspect)

類是對物體特徵的抽象,切面就是對橫切關注點的抽象

3、連接點(joinpoint)

被攔截到的點,因爲Spring只支持方法類型的連接點,所以在Spring中連接點指的就是被攔截到的方法,實際上連接點還可以是字段或者構造器

4、切入點(pointcut)

對連接點進行攔截的定義

5、通知(advice)

所謂通知指的就是指攔截到連接點之後要執行的代碼,通知分爲前置、後置、異常、最終、環繞通知五類

6、目標對象

代理的目標對象

7、織入(weave)

將切面應用到目標對象並導致代理對象創建的過程

8、引入(introduction)

在不修改代碼的前提下,引入可以在運行期爲類動態地添加一些方法或字段

二、通知

一個類的整個方法被自動攔截。

1.通知類型

  spring aop中,有四種類型通知的支持:

  ①在通知之前:該方法執行運行前運行

  ②通知返回之後:運行後,該方法返回一個結果

  ③通知拋出之後:運行方法拋出異常後

  ④環繞通知:環繞方法執行運行,結合以上三個通知

2 實例

①在通知之前:

1.創建 java project

2.創建接口User.java

package com.spring;

public interface User {
	void printName();
	void printAge();
        void printThrowException();

}

 3.創建實現類IUser.java,實現User接口

package com.spring;

public class User implements IUser {
	private String name;
	private Integer age;
	
	public void setName(String name) {
		this.name = name;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	@Override
	public void printName() {
		System.out.println("我的名字是:"+name);
		
	}
	@Override
	public void printAge() {
		System.out.println("我的今年的年齡是:"+age);
		
	}
	public void printThrowException() {
		throw new IllegalArgumentException();
	}
}

4.創建一個實現 MethodBeforeAdvice 接口的類 UserBeforeMethod

package com.spring;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;
/**
  * 之前通知
 * 他會在方法執行之前執行
 * 
 * 
 */
public class UserBeforeMethod implements MethodBeforeAdvice{

	@Override
	public void before(Method arg0, Object[] arg1, Object target) throws Throwable {
		System.out.println("UserbeforeMethod:before method  //執行業務邏輯方法前要執行的代碼功能");
	}

}

5.applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<!-- 目標類,使用動態代理實現aop時,目標類必須要實現接口 -->
	<bean name="user" class="com.spring.User">
	   <property name="name" value="石義賓"/>
	   <property name="age" value="26"/>
	</bean>
	<!-- 新的代理對象,在業務邏輯方法之前要執行的功能 -->
	<bean name="userProxyBean" class="com.spring.UserBeforeMethod"></bean>
	
	<!-- ProxyFactoryBean:產生代理類的工廠 ,結合代理類對象和目標對象生成新的代理對象-->
	<bean name ="ProxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
	<!-- interceptorNames屬性:指明要在代理的目標類中添加的功能,即advice -->
	<property name="interceptorNames">
	   <list>
	         <value>userProxyBean</value>
	   </list>
	</property>
	<!-- target屬性:指明要代理的目標類 ,這個目標類實現了上面proxyInterfaces屬性指定的接口 -->
	<property name="target" >
	<ref bean="user"/>
	</property>
	
	<!-- proxyInterfaces屬性:指明要代理的接口,可以不指定 -->
	<!-- <property name="proxyInterfaces"></property>-->
    
    <!-- proxyTargetClass屬性:,如果這個屬性被設定爲“true”,說明 ProxyFactoryBean要代理的不是接口類,而是要使用CGLIB方式來進行代理 -->
    <!-- <property name="proxyTargetClass"></property> -->
	</bean>
	</beans>

6.測試類

package com.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
	public static void main(String[] args) {
		
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		      //User user = applicationContext.getBean(User.class);
		//必須轉成接口類型
                //得到的是新的ProxyFactoryBean bean,而不是原來的user bean
                //它將運行 HijackBeforeMethod 的 before() 方法,在每個 CustomerService 的方法之前執行。
		IUser user = (IUser)applicationContext.getBean("ProxyFactoryBean");
		      System.out.println("*********name開始***************");
		      user.printName();
		      System.out.println("*********name結束***************");
		      System.out.println("*********age開始****************");
		      user.printAge();
		      System.out.println("*********age結束****************");
	}

}

②返回後通知

1-3如上

4.創建一個實現 AfterReturningAdvice接口的類 UserAfterMethod

package com.spring;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;
/** 
 * 該方法返回一個結果之後它將執行
 * 
 */
public class UserAfterMethod implements AfterReturningAdvice{

	@Override
	public void afterReturning(Object var1, Method var2, Object[] var3, Object var4) throws Throwable {
		System.out.println("UserAfterMethod:after method  //執行業務邏輯方法返回結果之後要執行的代碼功能");
	}

}

5.與上類似,只需要將applicationContext.xml中的bean userProxyBean對應的類改成UserAfterMethod即可

6.測試  ---如上

 

③通知拋出之後

1-3如上

4.創建一個實現 ThrowsAdvice接口的類 UserThrowExepection

package com.spring;

import org.springframework.aop.ThrowsAdvice;

/**
 * 
 * 它將在執行方法拋出一個異常後
 * 
 *
 */

public class UserThrowExpection implements ThrowsAdvice{
	//創建一個afterThrowing方法攔截拋出:IllegalArgumentException異常。 
	public void afterThrowing(IllegalArgumentException e)throws Throwable {
		//執行業務邏輯方法之後,會拋出一個異常,該方法會捕獲異常並執行
		System.out.println("UserThrowExpection:Throw exception");
		
	}

}

5.與上類似,只需要將applicationContext.xml中的bean userProxyBean對應的類改成UserThrowExepection即可

6.測試

package com.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
	public static void main(String[] args) {
		
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
		      //User user = applicationContext.getBean(User.class);
		//必須轉成接口類型
		IUser user = (IUser)applicationContext.getBean("ProxyFactoryBean");
		      System.out.println("*********name開始***************");
		      user.printName();
		      System.out.println("*********name結束***************");
		      System.out.println("*********age開始****************");
		      user.printAge();
		      System.out.println("*********age結束****************");
		      
		      try {
		    	  //拋出一個異常,就會被UserThrowExpection捕獲
		    	  user.printThrowException();
		      } catch(Exception e) {
		    	  
		      }
	}

}

④環繞通知

1-3如上

4.創建一個實現了MethodInterceptor接口的類UserAroundMethod

package com.spring;

import java.util.Arrays;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
 * 
 * 它結合了其它的三個通知,在方法執行過程中執行。這種通知也是常用的
 */
public class UserAroundMethod implements MethodInterceptor {

	@Override
	public Object invoke(MethodInvocation methodInvocation) throws Throwable {
		
		System.out.println("Method name : "
				+ methodInvocation.getMethod().getName());
		System.out.println("Method arguments : "
				+ Arrays.toString(methodInvocation.getArguments()));

		// same with MethodBeforeAdvice
		System.out.println("UserAroundMethod : Before method!");
		try {
			
			//必須調用“methodInvocation.proceed(); 繼續在原來的方法執行,否則原來的方法將不會執行。
			//相當於執行業務邏輯方法
			Object result = methodInvocation.proceed();
			
			System.out.println("UserAroundMethod :after method!");

			return result;
			
		}catch(IllegalArgumentException  e) {
			
			System.out.println("UserAroundMethod : Throw exception!");
			throw e;
		}
	}

}

5.與上類似,只需要將applicationContext.xml中的bean userProxyBean對應的類改成UserAroundMethod即可

6.測試

   Test如③

三、切入點

在二的通知中都是一個類的整個方法都被攔截下來,但是在大多數情況下可能只需要一種方式來攔截一個或者兩個方法,

這就是爲什麼要引入切入點,它允許通過它的方法名來攔截方法。另外一個切入點必須具有advisor相關聯。

spring aop中有三個專業術語:

  • Advice – 指示之前或方法執行後採取的行動。
  • Yiibaicut – 指明哪些方法應該攔截,通過方法的名稱或正則表達式模式。
  • Advisor – 分組"通知"和”切入點“成爲一個單元,並把它傳遞到代理工廠對象。

可以通過以下兩種方式匹配方法:

  1. 名稱匹配
  2. 正則表達式匹配

1.實例

(1)名稱匹配

  1-3如上

  4.不需要創建相關的通知類。Spring提供了PintcutAdvisor類來保存工作聲明advisor和切入點到不同的bean,

    可以使  用 NameMatchMethodPointcutAdvisor 兩者結合成一個 bean。直接在配置文件中配置。

  5.applicationContext.xml

     5.1 通過“切入點”和“advisor”攔截printName()方法。創建NameMatchMethodPointcut切入點bean,並提出

           要在“mappedName”屬性值來攔截方法名。

<bean id="userPointcut" class="org.springframework.aop.support.NameMatchMethodPointcut">
    	<property name="mappedName" value="printName"></property>
    </bean>

     5.2 創建 DefaultPointcutAdvisor 通知 bean,通知和切入點相關聯。

<bean id="userAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">    
    	<property name="pointcut" ref="userPointcut"></property>
    	<property name="advice" ref="userAroundMethod"></property>
    </bean>

5.3 更換代理“interceptorNames”到“customerAdvisor”(它是“userAroundMethod”)。

<bean id="customerserviceProxy"  class="org.springframework.aop.framework.ProxyFactoryBean">
    	<property name="target" ref="customerservice"></property>
    	<property name="interceptorNames">
    			<list>
    				<value>userAdvisor</value>
    			</list>
    	</property>
    </bean>

 

5.4 完整的applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<!-- 目標類,使用動態代理實現aop時,目標類必須要實現接口 -->
	<bean name="user" class="com.spring.User">
	   <property name="name" value="石義賓"/>
	   <property name="age" value="25"/>
	</bean>
	<!-- 通知 -->
	<bean id="userAroundMethod" class="com.spring.UserAroundMethod"></bean>
	<!-- 1:通過“切入點”和“advisor”攔截printName()方法。創建NameMatchMethodYiibaicut切入點bean,並提出要在“mappedName”屬性值來攔截方法名。  -->
	<!-- 代替之前的userProxyBean-->
	<bean id="userPointcut"
        class="org.springframework.aop.support.NameMatchMethodPointcut">
		<property name="mappedName" value="printName" />
	</bean>
	
	<!-- 2: 創建 DefaultPointcutAdvisor 通知 bean,通知和切入點相關聯-->
	<bean id="userAdvisor"
		class="org.springframework.aop.support.DefaultPointcutAdvisor">
		<property name="pointcut" ref="userPointcut" />
		<property name="advice" ref="userAroundMethod" />
	</bean>
	
	<!-- ProxyFactoryBean:產生代理類的工廠 ,結合代理類對象和目標對象生成新的代理對象-->
	<bean name ="ProxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
	<!-- interceptorNames屬性:指明要在代理的目標類中添加的功能,即advice -->
	<property name="interceptorNames">
	   <list>
	         <!--3: 更換代理 ,用customerAdvisor(結合切入點)代替之前的userProxyBean(單純通知)-->
	         <value>userAdvisor</value>
	   </list>
	</property>
	<!-- target屬性:指明要代理的目標類 ,這個目標類實現了上面proxyInterfaces屬性指定的接口 -->
	<property name="target" >
	<ref bean="user"/>
	</property>
	
	<!-- proxyInterfaces屬性:指明要代理的接口,可以不指定 -->
	<!-- <property name="proxyInterfaces"></property>-->
    
    <!-- proxyTargetClass屬性:,如果這個屬性被設定爲“true”,說明 ProxyFactoryBean要代理的不是接口類,而是要使用CGLIB方式來進行代理 -->
    <!-- <property name="proxyTargetClass"></property> -->
	</bean>
	</beans>

5.5 測試

      測試類不變,從結果可以,只攔截了printName()方法。

     

(2) 正則表達式

      可以通過使用正則表達式匹配切入點方法的名稱  – RegexpMethodPointcutAdvisor

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<!-- 目標類,使用動態代理實現aop時,目標類必須要實現接口 -->
	<bean name="user" class="com.spring.User">
	   <property name="name" value="石義賓"/>
	   <property name="age" value="25"/>
	</bean>
	<!-- 通知 -->
	<bean id="userAroundMethod" class="com.spring.UserAroundMethod"></bean>
	
	<!-- 2: 創建 DefaultPointcutAdvisor 通知 bean,通知和切入點相關聯-->
	<!--它攔截方法名稱中有“URL”的方法。在實踐中,可以用它來管理DAO層,聲明“.*DAO.*” 攔截所有的DAO類來支持事務-->
	<bean id="userAdvisor"
		class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
		 <!--不需要直接引入需要被代理的bean-->
		<property name="patterns">
		<list>
		<value>.*URL.*</value>
		</list>
		</property>
		<property name="advice" ref="userAroundMethod" />
	</bean>
	
	<!-- ProxyFactoryBean:產生代理類的工廠 ,結合代理類對象和目標對象生成新的代理對象-->
	<bean name ="ProxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
	<!-- interceptorNames屬性:指明要在代理的目標類中添加的功能,即advice -->
	<property name="interceptorNames">
	   <list>
	         <!--3: 更換代理 ,用customerAdvisor(結合切入點)代替之前的userProxyBean(單純通知)-->
	         <value>userAdvisor</value>
	   </list>
	</property>
	<!-- target屬性:指明要代理的目標類 ,這個目標類實現了上面proxyInterfaces屬性指定的接口 -->
	<property name="target" >
	<ref bean="user"/>
	</property>
	
	<!-- proxyInterfaces屬性:指明要代理的接口,可以不指定 -->
	<!-- <property name="proxyInterfaces"></property>-->
    
    <!-- proxyTargetClass屬性:,如果這個屬性被設定爲“true”,說明 ProxyFactoryBean要代理的不是接口類,而是要使用CGLIB方式來進行代理 -->
    <!-- <property name="proxyTargetClass"></property> -->
	</bean>
	</beans>

      在IUser接口中加上一個printURL()方法,並在User中實現重寫,然後在測試類中調用該方法。其結果如下:

    

     現在,它攔截方法名稱中有“URL”的方法,在實踐中,可以用它來管理DAO層,聲明“.*DAO.*” 攔截所有的

     DAO類來支持事務。

三、自動代理創建者

 在一和二中,必須手動創建一個代理bean(ProxyFactoryBean),對每個bean需要aop支持。這種方法並不有效,

因爲這種手動方式意味着,如果有一個客戶模塊,所有的dao類實現sql日誌支持(提醒)的aop功能,那麼就要針

每個dao創建對應的代理工廠bean,這就會導致bean配置文件會氾濫代理類。爲此spring提供了兩個自動代理創

建者來自動創建代理bean。

1.BeanNameAutoProxyCreator

   在此之前需要使用代理名稱來獲得bean:

   IUser user = (IUser)applicationContext.getBean("ProxyFactoryBean");

   在自動代理機制,只需要創建一個BeanNameAutoProxyCreator幷包含所有你的bean(通過bean的名字,或正則表達式名)和“advisor” 作爲一個單位。

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<!-- 目標類,使用動態代理實現aop時,目標類必須要實現接口 -->
	<bean name="userDao" class="com.spring.User">
	   <property name="name" value="石義賓"/>
	   <property name="age" value="25"/>
	</bean>
	<!-- 通知 -->
	<bean id="userAroundMethod" class="com.spring.UserAroundMethod"></bean>
	
	<!-- 2: 創建 DefaultPointcutAdvisor 通知 bean,通知和切入點相關聯-->
	<!--它攔截方法名稱中有“URL”的方法。在實踐中,可以用它來管理DAO層,聲明“.*DAO.*” 攔截所有的DAO類來支持事務-->
	<bean id="userAdvisor"
		class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
		 <!--不需要直接引入需要被代理的bean-->
		<property name="patterns">
		<list>
		<value>.*URL.*</value>
		</list>
		</property>
		<property name="advice" ref="userAroundMethod" />
	</bean>
	
<!--代替之前的ProxyFactoryBean-->
<bean
        class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <property name="beanNames">
            <list>
                <!--符合該正則的bean-->
                <value>*Dao</value>
            </list>
        </property>
        <property name="interceptorNames">
            <list>
                <value>customerAdvisor</value>
            </list>
        </property>
    </bean>
	</beans>

現在,可以通過“userDao”的原始名稱獲取bean, 如果知道這個bean已經代理。

IUser user = (IUser)appContext.getBean("userDao");

2.DefaultAdvisorAutoProxyCreator

   DefaultAdvisorAutoProxyCreator是非常強大的,如果有bean相關聯,spring會自動創建一個代理。

  

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<!-- 目標類,使用動態代理實現aop時,目標類必須要實現接口 -->
	<bean name="userDao" class="com.spring.User">
	   <property name="name" value="石義賓"/>
	   <property name="age" value="25"/>
	</bean>
	<!-- 通知 -->
	<bean id="userAroundMethod" class="com.spring.UserAroundMethod"></bean>
	
	<!-- 2: 創建 DefaultPointcutAdvisor 通知 bean,通知和切入點相關聯-->
	<!--它攔截方法名稱中有“URL”的方法。在實踐中,可以用它來管理DAO層,聲明“.*DAO.*” 攔截所有的DAO類來支持事務-->
	<bean id="userAdvisor"
		class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
		 <!--不需要直接引入需要被代理的bean-->
		<property name="patterns">
		<list>
		<value>.*URL.*</value>
		</list>
		</property>
		<property name="advice" ref="userAroundMethod" />
	</bean>
<!--不需要指定任何,自動根據bean去引入-->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/></beans>

五、AspectJ

AspectJ註解集成到spring aop中,可以很輕鬆實現方法的攔截。

常見的AspectJ的註解:

  1. @Before – 方法執行前運行
  2. @After – 運行在方法返回結果後
  3. @AfterReturning – 運行在方法返回一個結果後,在攔截器返回結果。
  4. @AfterThrowing – 運行方法在拋出異常後,
  5. @Around – 圍繞方法執行運行,結合以上這三個通知。

 

六、spring aop在ssm(spring+springmvc+mybatis)中的配置使用

這裏以事務爲例。

我們只需要在spring-mybatis.xml文件中配置如下:

1.導入aop的引用:

   xmlns:aop="http://www.springframework.org/schema/aop"
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd

 2.配置spring的事務管理器

<!-- 事務核心管理器,封裝了所有事務操作. 依賴於連接池 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

3.配置aop全局事務管理

<!--aop全局事務管理(下面基於dao層)-->
    <aop:config>
        <aop:pointcut id="allDaoMethods"
                      expression="execution(* com..dao..*(..))"/>
        <aop:advisor advice-ref="defaultTransactionAdvice"
                     pointcut-ref="allDaoMethods"/>
    </aop:config>

4.配置事務管理的通知(具體指定aop攔截到的哪些方法需要創建/使用事務)

<tx:advice id="defaultTransactionAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!--<tx:method name="*" isolation="DEFAULT"-->
                    <!--propagation="REQUIRED" no-rollback-for="java.lang.RuntimeException" timeout="100"/>-->
            <!--<tx:method name="*" read-only="true"/>-->
            <!-- 以方法爲單位,指定方法應用什麼事務屬性 isolation:隔離級別 propagation:傳播行爲 read-only:是否只讀 -->
            <!--PROPAGATION_REQUIRED:支持當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇。-->
            <!--PROPAGATION_SUPPORTS:支持當前事務,如果當前沒有事務,就以非事務方式執行。-->
            <!--PROPAGATION_MANDATORY:支持當前事務,如果當前沒有事務,就拋出異常。-->
            <!--PROPAGATION_REQUIRES_NEW:新建事務,如果當前存在事務,把當前事務掛起。-->
            <!--PROPAGATION_NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。-->
            <!--PROPAGATION_NEVER:以非事務方式執行,如果當前存在事務,則拋出異常。-->
            <!--PROPAGATION_NESTED:支持當前事務,如果當前事務存在,則執行一個嵌套事務,如果當前沒有事務,就新建一個事務。-->
 
            <tx:method name="save*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
            <tx:method name="Borrow*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
            <tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
            <tx:method name="create*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
            <tx:method name="insert*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
            <tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
            <tx:method name="merge*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
            <tx:method name="del*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
            <tx:method name="remove*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
            <tx:method name="put*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
            <tx:method name="use*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
        </tx:attributes>
    </tx:advice>

七、spring aop在ssh(struts2+spring+hibernate)中的配置使用

1.如上

2.配置spring的事務管理器

   <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">

       <property name="sessionFactory">

           <ref local="sessionFactory"/>

       </property>

    </bean>

3.配置bean事務有兩種方式

   第一種方式:使用TransactionProxyFactoryBean創建事務代理

	<!-- 事務 -->
	<bean id="baseServiceProxy"
		class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
		<property name="transactionManager">
			<ref bean="transactionManager" />
		</property>
		<property name="target">
                        <!--使用事務的bean-->
			<ref local="baseService" />
		</property>
		<property name="transactionAttributes">
			<props>
				<prop key="insert*">PROPAGATION_REQUIRED</prop>
				<prop key="delete*">PROPAGATION_REQUIRED</prop>
				<prop key="update*">PROPAGATION_REQUIRED</prop>
				<prop key="search*">readOnly</prop>
				<prop key="list*">readOnly</prop>
			</props>
		</property>
	</bean>

第二種方式:

先配置事務傳播性

<!-- 配置事務的傳播特性 -->

    <tx:advice id="txAdvice" transaction-manager="transactionManager" >

       <tx:attributes>

           <!-- 在開發的時候可以這樣定義,但部署的時候一定要詳細定義 -->

           <tx:method name="*" propagation="REQUIRED"/>

       <!--  

           <tx:method name="add*" propagation="REQUIRED"/>

           <tx:method name="del*" propagation="REQUIRED"/>

           <tx:method name="update*" propagation="REQUIRED"/>

           <tx:method name="*" read-only="true"/>

       -->

       </tx:attributes>

    </tx:advice>
    <!-- 配置哪些類哪些方法使用事務 -->

    <aop:config>

       <aop:pointcut id="txAdvicePointcut" expression="execution(* com.nuist.service.*.*(..))"/>

       <aop:advisor advice-ref="txAdvice" pointcut-ref="txAdvicePointcut"/>

    </aop:config>

事務可以通過註解來進行聲明,在以後的章節中會詳細講事務。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章