spring之AspectJ實現AOP
一、基於註解的AspectJ
1、要在spring應用中使用AspectJ註解,必須在classpath下包含AspectJ類庫:
com.springsource.org.aopalliance.jar 和 com.springsource.org.aspectj.weaver.jar;將aop schema添加到 <beans> 根元素中;在Spring IoC 容器中啟用 AspectJ直接支持,只要在 bean 配置文件中定義一個空的XML元素 <aop:aspectj-autoproxy>;當Spring IoC 容器檢測到 bean 配置文件中的 <aop:aspectj-autoproxy>
2、通知是標有某種註解的簡單的java方法,AspectJ支持5種類型的通知註解:
1)@Before:前置通知,在方法執行之前執行
2)@After:最終增強
3)@AfterReturning:後置通知,在方法返回結果之後執行
4)@AfterThrowing:異常通知,在方法拋出異常後執行
5)@Around:環繞通知,圍繞著方法的執行
3. 典型的切點表達式是根據方法的簽名來匹配各種方法:
-execution(* *.*(..)):第一個*代表匹配任意修飾符和返回值,第二個*代表任意類的對象,第三個*代表任意方法,參數列表中..匹配任意數量的參數。
- execution (* com.bupt.springtest.aop.ArithmeticCalculator.*(..)):匹配 ArithmeticCalculator 中聲明的所有方法,第一個 * 代表任意修飾符及任意返回值;第二個 * 代表任一方法; .. 匹配任意數量的參數。若目標類或接口與該切面在同一個包中,可以省略包名。
- execution (public * ArithmeticCalculator.*(..)):匹配ArithmeticCalculator 類中的所有公有方法。 - execution (public double ArithmeticCalculator.*(..)):匹配ArithmeticCalculator 中返回double類型數值的方法- execution (public double ArithmeticCalculator.*(double, ..)):匹配第一個參數為double類型的方法, .. 匹配任意數量任意類型的參數
- execution (public double ArithmeticCalculator.*(double, double)):匹配參數類型為double, double類型的方法
4、案例
1、創建一個接口
package cn.happy.service; public interface ISomeService { public void doSome(); public String add(); public void insert(); public void update(); public void delete(); public void select(); }
2、實現接口類
package cn.happy.service; public class SomeService implements ISomeService { public void doSome() { System.out.println("code ok"); } public String add() { System.out.println("=========log日誌==============="); //int i = 5/0; return "add"; } public void insert() { System.out.println("insert"); } public void update() { System.out.println("update"); } public void delete() { System.out.println("delete"); } public void select() { int i = 5/0; System.out.println("select"); } }
3、編寫增強類
package cn.happy.service; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; @Aspect public class MyAspect { @Before(value="execution(* *..service.*.*(..))") public void myAspectj(){ System.out.println("---我是前置增強---"); } @AfterReturning(value="execution(* *..service.*.*(..))") public void myAspectjAfter(){ System.out.println("---我是後置增強---"); } @Around(value="execution(* *..service.*.*(..))") public Object myAspectjAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("---我是環繞前增強---"); Object result = proceedingJoinPoint.proceed(); System.out.println("---我是環繞後增強---"); if (result!= null) { String str = (String)result; //可以改變返回值 return str.toUpperCase(); } else { return null; } } 異常增強 @Pointcut("execution(* *..service.*.*(..))") 表達式註解 public void myPoincut(){} @AfterThrowing("myPoincut()") public void throwing(){ System.out.println("---error---"); } //切點表達式 @Pointcut("execution(* *..service.*.insert(..))") public void insert(){} @Pointcut("execution(* *..service.*.update(..))") public void update(){} @Pointcut("execution(* *..service.*.delete(..))") public void delete(){} @Before("insert()||update()||delete()") public void myAspectj(){ System.out.println("---我是前置增強開啟事物---"); } //最終增強 @After("execution(* *..service.*.*(..))") public void after(){ System.out.println("我是最終增強"); } }
4、編寫xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p" 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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <!--註解實現--> <!--目標對象--> <bean id="SomeService" class="cn.happy.serviceXML.SomeService"></bean> <!--增強 通知–> --> <bean id="beforeAdvice" class="cn.happy.service.MyAspect"></bean> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
5、編寫測試類
package cn.happy; import cn.happy.service.ISomeService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class test { @Test public void testAspect(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); ISomeService someService = (ISomeService)context.getBean("SomeService"); someService.insert(); someService.update(); someService.delete(); someService.select(); } }
二、基於xml的AspectJ實現
1、基於xml的實現需要在xml配置文件中加入<aop>節點。
2、案例
1)創建接口類
package cn.happy.serviceXML; public interface ISomeService { public void doSome(); public String add(); }
2)實現接口類
package cn.happy.serviceXML; public class SomeService implements ISomeService { public void doSome() { System.out.println("code ok"); } public String add() { System.out.println("log------"); //int i = 5/0; return "add"; } }
3)編寫增強類
package cn.happy.serviceXML; import org.aspectj.lang.ProceedingJoinPoint; public class MyAspect { public void myBefore(){ System.out.println("=========before============"); } public void after(){ System.out.println("============after==============="); } public Object myArround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("我是環繞前增強"); Object result = proceedingJoinPoint.proceed(); System.out.println("我是環繞後增強"); if (result!= null) { String str = (String)result; //可以改變返回值 return str.toUpperCase(); } else { return null; } }
}
4).編寫xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p" 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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <!--目標對象--> <bean id="SomeService" class="cn.happy.serviceXML.SomeService"></bean> <!--增強類--> <bean id="aspect" class="cn.happy.serviceXML.MyAspect"></bean> <!--aop--> <aop:config> <!--設置一個切點--> <aop:pointcut id="mycut" expression="execution(* *..serviceXML.*.*(..))"></aop:pointcut> <aop:aspect ref="aspect"> <aop:before method="myBefore" pointcut-ref="mycut"></aop:before> <!--<aop:after-returning method="after" pointcut-ref="mycut"></aop:after-returning>--> <!--<aop:around method="myArround" pointcut-ref="mycut"></aop:around>--> </aop:aspect> </aop:config> </beans>
5)編寫測試類
package cn.happy; import cn.happy.serviceXML.ISomeService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class test01 { // AspectJ XML @Test public void testAspectXML(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); ISomeService someService= (ISomeService)context.getBean("SomeService"); someService.add(); someService.doSome(); } }
spring之AspectJ實現AOP