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方法中進行了限制,調用的目標對象的方法不會執行。