org.springframework.aop
包中的。通知名稱 | 接口 |
---|---|
前置通知 | org.springframework.aop.MethodBeforeAdvice |
後置返回通知 | org.springframework.aop.AfterReturningAdvice |
後置通知 | org.springframework.aop.AfterAdvice |
環繞通知 | org.springframework.aop.MethodInterceptor |
異常通知 | org.springframework.aop.ThrowsAdvice |
引入通知 | org.springframework.aop.IntroductionInterceptor |
寫一個公共類,用於目標對象前端
public class Person { private String name; public boolean saySomething(String something){ System.out.println("Pereson類中說了一句:"+something); return true;//默認返回true } public String getName() { return name; } public void setName(String name) { this.name = name; } }
前置通知能夠修改傳遞給方法的參數,而且能夠經過拋出異常來阻止方法的執行,能夠用前置通知實現用戶登陸的驗證,SpringSecurity就是這麼作的java
/** * 前置通知類 */ public class BeforeAdvice implements MethodBeforeAdvice { @Override public void before(Method method, Object[] objects, @Nullable Object o) throws Throwable { //第一個參數是目標方法對象,第二個是參數,第三個是作爲調用目標的object(這是personr實例) //打印方法名 System.out.println("要執行的方法是:"+method.getName()); //修改參數爲lyn4ever objects[0]="lyn4ever";//咱們修改爲爲了lyn4ever,因此打印出來的就是lyn4ever,而不是zhangsan } public static void main(String[] args) { Person person = new Person(); ProxyFactory pf =new ProxyFactory(); pf.addAdvice(new BeforeAdvice()); pf.setTarget(person); Person proxy = (Person) pf.getProxy(); //我這裏傳的參數是zhangsan,理論上它應該打印出來zhangsan proxy.saySomething("zhangsan"); } }
沒毛病,原本我輸入的是zhangsan,在aop中將參數改成了lyn4ever,這樣就完美的替換了。git
是在鏈接點(方法調用)返回後執行,這顯然不能像上邊那樣修改參數,也不能修改返回值。可是能夠拋出能夠發送到堆棧的異常,一樣也能夠調用其餘方法。github
/** * 後置返回通知 */ public class AfterReturnAdvice implements AfterReturningAdvice { @Override public void afterReturning(@Nullable Object o, Method method, Object[] objects, @Nullable Object o1) throws Throwable { /* 參數和前置通知是同樣的 這個是在返回以後調用,所以,person中的saySomething會先打印,咱們在這裏修改的參數不起做任何做用 */ System.out.println("調用的方法是:"+method.getName()+"這句是在saySomething以後");//這句是在saySomething以後 objects[0]="lyn4ever";//這句能夠修參數,可是以前的方法已經執行過了,因此不起任何做用 System.out.println("咱們修改了參數爲:"+objects[0]+"可是沒有任何用");//這時候這個參數並不會傳到person.saysomething(),由於已經調用過了 } public static void main(String[] args) { Person person = new Person(); ProxyFactory pf = new ProxyFactory(); pf.addAdvice(new AfterReturnAdvice());//注意修改這個爲當前類中的通知類 pf.setTarget(person); Person proxy = (Person) pf.getProxy(); proxy.saySomething("zhangsan"); } }
這人最好理解了,就是在方法調用先後均可以執行代碼。看起來像是前置後後置的集合,可是它能夠修改方法的返回值,由於它實現的invoke方法的返回值是Object,因此咱們就能夠修改,而前置通知的返回是void,因此無法修改的。甚至以致於咱們能夠不調用目標對象中的鏈接點方法,咱們徹底修改這個方法的所有代碼。spring
public class MyMethodInterceptor implements MethodInterceptor { @Override public Object invoke(MethodInvocation invocation) throws Throwable { return null; } }
雖然這個invoke()方法中並無提供像以前的那些參數,可是這一個invocation實例能夠獲得
代碼示例ide
/** * 環繞通知 */ public class MyMethodInterceptor implements MethodInterceptor { @Override public Object invoke(MethodInvocation invocation) throws Throwable { //在這個invoation中有一切咱們想要的方法相關 System.out.println("類名是:"+invocation.getThis().getClass().getName()); System.out.println("目標方法是:"+invocation.getMethod().getName()); Object[] arguments = invocation.getArguments();//這個就是參數 System.out.println("第一個參數 是:"+arguments[0]); //咱們修改第一個參數爲lyn4ever arguments[0]="lyn4ever"; invocation.proceed();//執行目標方法 System.out.println("這個是在以後執行的"); return false;//修改返回值 } public static void main(String[] args) { Person person = new Person(); ProxyFactory pf = new ProxyFactory(); pf.addAdvice(new MyMethodInterceptor());//注意修改這個爲當前類中的通知類 pf.setTarget(person); Person proxy = (Person) pf.getProxy(); boolean flag = proxy.saySomething("zhangsan"); System.out.println(flag);//方法原本是要返回true的 } }
能夠看到,咱們修改了目標方法返回的值。ui
本文demo已提交至githubthis