1. Before:在目標方法執行之前執行織入,如果Before的處理中沒有進行特殊的處理,那麼目標方法最終會執行,但是如果想要阻止目標方法執行時,可以通過拋出一個異常來實現,Before處理無法拿到目標方法的返回值,因為這時候目標方法並未運行。
2. AfterReturning: 返回之後執行(前提是目標方法執行成功),可以訪問到目標對象的返回值,但是不可以改變返回值。
3. AfterThrowing:拋出異常之後執行,可以對異常進行適當的修復或者將異常輸出到日志中。
4. After:不管目標對象執行成功與否都會被織入常用於釋放資源等。
5. Around:既可以在目標方法之前,又可以在目標方法調用之後執行,但是需要在線程安全的情況下執行,如果需要目標方法執行之前或者之後共享某種數據,應該考慮用Around。需要改變返回值的時候,只能使用Around。
上一篇文章中已經提到,通過JDK的代理生成AOP代理對象的方式,但是前提是目標方法實現了接口,如果沒有實現接口的話,那麼怎麼辦?
在這種情況下,我們使用cglib來實現生成AOP代理對象。
定義一個沒有實現接口的User類。
package com.siti.spring20160315; public class User { private String userName; private String password; public User(){} public User(String userName, String password) { super(); this.userName = userName; this.password = password; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public void saySth() { System.out.println("hello!"); } }對於Spring而言,如果說目標類實現了接口的話,會按照JDK代理生成AOP代理對象,如果沒有實現接口的話,那麼會使用cglib來生成AOP代理對象。
package com.siti.spring20160315; import java.lang.reflect.Method; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.InvocationHandler; public class MyProxy4AOPObject implements InvocationHandler{ private Object targetObj; public Object getProxyObject(Object targetObj){ this.targetObj = targetObj; Enhancer enhance = new Enhancer(); // 將目標類設置為代理對象的父類,產生目標類的子類,這個子類覆蓋所有父類的非final修飾的方法 enhance.setSuperclass(this.targetObj.getClass()); // 設置回調,可以單獨建立一個類實現InvocationHandler接口實現裡面的invoke方法 enhance.setCallback(this); return enhance.create(); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { User user = (User)this.targetObj; Object result = null; try{ // 攔截,符合要求的才允許運行 if(user.getUserName() != null && user.getUserName() != ""){ // -->Before result = method.invoke(this.targetObj, args); // -->AfterReturning } }catch (Exception e) { // -->AfterThrowing }finally{ // -->After } return result; } }
package com.siti.spring20160315; public class MainTest { public static void main(String[] args) { User user = new User("wy", "wy"); MyProxy4AOPObject myProxy4AOPObject = new MyProxy4AOPObject(); User us = (User) myProxy4AOPObject.getProxyObject(user); us.saySth(); } }這裡會輸出:hello!
如果將User中name屬性賦值為null或者""的話就不會輸出,因為在invoke方法中進行了限制,調用的目標對象的方法不會執行。