本教程對應視頻課程:http://edu.51cto.com/course/14731.htmlhtml
Aspect oritention programming(面向切面編程),Spring的AOP使用動態代理實現,若是一個類實現了接口,那麼spring就使用JDK的動態代理完成AOP,若是一個類沒有實現接口,那麼spring就是用cglib完成AOP;java
AOP當中的概念:spring
①切入點Pointcut:在哪些類,哪些方法上面切(where);express
②通知/加強Advice:在方法的什麼時機(when)作什麼(what);編程
③切面Aspect:切入點+通知:什麼時間,什麼地點,幹什麼dom
④織入Weaving:把切面加入到對象,並建立出代理對象的過程(Spring自動搞定)ide
一、添加jar包spa
com.springsource.org.aopalliance-1.0.0.jar、com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar代理
二、引入aop的命名空間code
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <context:property-placeholder location="classpath:db.properties"/> <context:component-scan base-package="cn.org.kingdom"/> </beans>
三、xml配置
<aop:config> <!--作什麼 --> <aop:aspect ref="txManager"> <!--什麼地點,哪些方法上--> <aop:pointcut expression="execution(* cn.org.kingdom.aop_xml.*ServiceImpl.*(..)) " id="txPoint"/> <!--時機:方法前、方法後、方法先後 --> <aop:before method="beginTransaction" pointcut-ref="txPoint"/> </aop:aspect> </aop:config>
注意執行表達式的格式:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)
modifiers-pattern:修飾符
ret-type-pattern:返回值的類型
declaring-type-pattern:這個方法的類名
name-pattern:方法名
param-pattern:參數
throws-pattern:異常
語法案例:
1.任意公共方法的執行: execution(public * *(..)) 2.任何一個名字以「set」開始的方法的執行: execution(* set*(..)) 3.AccountService接口定義的任意方法的執行: execution(* com.xyz.service.AccountService.*(..)) 4.在service包中定義的任意方法的執行: execution(* com.xyz.service.*.*(..)) 5.在service包或其子包中定義的任意方法的執行: execution(* com.xyz.service..*.*(..))
aop:before(前置通知):在方法執行以前執行加強操做(加強類中的指定加強方法)
<aop:before method="beginTransaction" pointcut-ref="txPoint"/>
aop:after-returning(後置通知):在方法正常執行完成以後執行加強操做;
<aop:after-returning method="commit" pointcut-ref="txPoint"/>
異常通知:在業務方法中出現異常,須要調用的加強操做 throwing="ex":決定方法定義爲:public void rollback(Throwable ex):
<aop:after-throwing method="rollback" pointcut-ref="txPoint" throwing="ex"/>
aop:after(最終通知):在方法執行以後執行,至關於在finally裏面執行
<aop:after method="close" pointcut-ref="txPoint"/>
aop:around(環繞通知):把方法的執行包裹起來,環繞通知有兩個要求
一、方法必需要返回一個Object(返回的結果)
二、方法的第一個參數必須是ProceedingJoinPoint(能夠繼續向下傳遞的切入點)
<aop:around method="around" pointcut-ref="txPoint"/>
完整代碼
//PersonService package cn.org.kingdom.service; public interface PersonService { public abstract int add(String msg); } //PersonServiceImpl package cn.org.kingdom.service.impl; import org.springframework.stereotype.Service; import cn.org.kingdom.service.PersonService; @Service("personService") public class PersonServiceImpl implements PersonService { public int add(String msg) { System.out.println("執行add操做"); System.out.println(10/0); return 0 ; } } //事務管理類 package cn.org.kingdom.ts; import org.aspectj.lang.ProceedingJoinPoint; import org.springframework.stereotype.Component; @Component("ts") public class Transaction { public void begin(){ System.out.println("開啓事務"); } public void commit(){ System.out.println("提交事務"); } public void rollback(Throwable ex){ System.out.println("回滾事務"); System.out.println("發生的異常通知是:"+ex); } public void closeConnection(){ System.out.println("關閉鏈接"); } public Object around(ProceedingJoinPoint pjp){ Object value = null ; try{ begin(); value = pjp.proceed(); commit(); }catch(Throwable e) { rollback(e); }finally{ closeConnection(); } return value; } }
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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <context:property-placeholder location="classpath:db.properties"/> <!-- 掃包 --> <context:component-scan base-package="cn.org.kingdom"/> <aop:config> <aop:aspect ref="ts"> <aop:pointcut expression="execution(* cn.org.kingdom.service..*.*(..))" id="mypointcut"/> <aop:around method="around" pointcut-ref="mypointcut"/> </aop:aspect> </aop:config> </beans>
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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <context:property-placeholder location="classpath:db.properties"/> <!-- 掃包 --> <context:component-scan base-package="cn.org.kingdom"/> <aop:aspectj-autoproxy/> </beans>
java配置
package cn.org.kingdom.ts; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Component("ts") @Aspect public class Transaction { @Pointcut(value="execution(* cn.org.kingdom.service..*.*(..))") public void pointcut(){} //注意value爲方法名,而且加括號 @Around(value="pointcut()") public Object around(ProceedingJoinPoint pjp){ Object value = null ; try{ begin(); value = pjp.proceed(); commit(); }catch(Throwable e) { rollback(e); }finally{ closeConnection(); } return value; } public void begin(){ System.out.println("開啓事務"); } public void commit(){ System.out.println("提交事務"); } public void rollback(Throwable ex){ System.out.println("回滾事務"); System.out.println("發生的異常通知是:"+ex); } public void closeConnection(){ System.out.println("關閉鏈接"); } }