Spring AOP 的使用過程理解
首先,aop的使用場景介紹:
1、處理一些通用的非功能性的需求,不影響業務流程,比如說打印日志、性能統計、推送消息等;
2、aop無法攔截static、final方法、private方法
3、無法攔截內部方法調用
如果只要訪問目標方法的參數,Spring還提供了一種更簡單的方法:我們可以在程序中使用args來綁定目標方法的參數。如果在一個args表達式中指定了一個或多個參數,則該切入點將只匹配具有對應形參的方法,且目標方法的參數值將被傳入增強處理方法。
Person.java :
public interface Person { public String sayHello(String name); public void eat(String food,Date time); }
Chinese.java :
@Component public class Chinese implements Person { @Override public void eat(String food, Date time) { System.out.println("我正在吃"+food+",現在時間是:"+time); } @Override public String sayHello(String name) { return name+" Hello,Spring AOP"; } }
AccessArgAspect.java :
@Aspect public class AccessArgAspect { @AfterReturning(returning="retVal", pointcut="execution(* com.bean.*.*(..)) && args(food,time)") public void access(String food,Date time,Object retVal){ System.out.println("目標方法中Strig參數為:"+food); System.out.println("目標方法中Date參數為:"+time); System.out.println("模擬記錄日志..."); } }
bean.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" 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.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <context:component-scan base-package="com.bean"> <context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/> </context:component-scan>
<aop:aspectj-autoproxy/> </beans>
Test.java
public class Test { public static void main(String[] args) { ApplicationContext ctx=new ClassPathXmlApplicationContext("bean.xml"); Person p=(Person) ctx.getBean("chinese"); System.out.println(p.sayHello("張三")); p.eat("西瓜",new Date()); } }
運行程序,控制台輸出:
切入點表達式部分增加了&&args(food,time)部分,意味着可以在增強處理方法中定義food和time兩個形參------定義這兩個形參時,形參類型可以隨意指定,但是一旦指定,譬如這里分別是String類型和Date類型,這兩個形參類型將用於限制該切入點只匹配第一個參數類型為String,第二個參數類型為Date的方法。
我們如果修改access方法的形參列表為:
public void access(int food,Date time,Object retVal)
那么該切入點表達式只能匹配第一個形參類型為int,第二個形參類型為Date的方法,此例子中沒有這樣的方法,也就匹配不上。此時運行程序,看控制台輸出:
可以看到沒有方法匹配上,程序里的增強處理沒起作用。
至此可以看出,使用 args表達式 有如下兩個作用:
① 提供了一種簡單的方式來訪問目標方法的參數。
② 可用於對切入表達式增加額外的限制。
除此之外,使用args表達式時還可使用如下形式:args(name,age,..),這表明增強處理方法中可以通過name,age來訪問目標方法的參數。注意上面args表達式括號中的2點,它表示可以匹配更多參數。