本文主要講的是如何使用JDK動態代理實現簡單的AOP。AOP是啥?若是你想在某些方法執行先後插入一些通用的處理,你能夠考慮AOP。java
JDK中提供了一個Proxy
類用於建立動態代理對象的靜態方法,若是在程序中爲一個或多個接口動態地生成實現類,就能夠使用Proxy來建立動態代理類。 Proxy
提供了下面的方法來建立動態代理實例:ide
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)測試
該代理對象的實現類實現了interfaces所指定的系列接口,執行代理對象的每一個方法時都會被替換執行InvocationHandler
對象的invoke
方法this
InvocationHandler是一個接口,在建立動態代理實例的時候須要把一個InvocationHandler
的實現類傳進去,那麼執行代理對象的每一個方法時就會被替換成執行InvocationHandler實現類中的invoke方法,至於這個invoke方法要怎麼實現,就由用戶本身決定。spa
在java.lang.reflect.Method
包中有一個方法代理
public Object invoke(Object obj, Object... args)code
該方法能夠實現對象方法的調用,它是Method
類的實例方法,該方法中的參數obj
是調用方法的對象,args
是用於方法調用的參數。對象
Pig接口,就定義了兩個方法接口
public interface Pig {
void info();
void run();
}
複製代碼
Pig的實現類,咱們要作的就是在這兩個方法執行的先後插入本身一些額外的操做get
public class FatPig implements Pig {
@Override
public void info() {
System.out.println("我是一頭小肥豬!");
}
@Override
public void run() {
System.out.println("我要跑步啦!");
}
}
複製代碼
LogUtils,須要在代理對象方法執行先後調用的方法
public class LogUtils {
public void before() {
System.out.println("==== 方法開始執行 ====");
}
public void after() {
System.out.println("==== 方法執行結束 ====");
}
}
複製代碼
PigInvocationHandler,該類實現了InvocationHandler接口。咱們定義了一個Object類型的實例變量,由於咱們須要在invoke方法中調用被代理對象的實現類的對應的方法。在invoke方法中,有兩個關鍵的參數:method
表明正在執行的方法,args
表明調用目標方法時傳入的實參。而後咱們就能夠在執行代理對象的方法先後自由插入本身的方法了。
public class PigInvocationHandler implements InvocationHandler {
// 須要被代理的對象
private Object target;
public void setTarget(Object target) {
this.target = target;
}
// 執行動態代理對象的全部方法時,都會被替換成執行以下的invoke方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
LogUtils logUtils = new LogUtils();
// 執行logUtils對象中的before方法
logUtils.before();
// 以target做爲主調來執行method方法
Object result = method.invoke(target, args);
// 執行logUtils對象中的after方法
logUtils.after();
return result;
}
}
複製代碼
測試類
public class MyProxyFactory {
// 爲指定的target生成動態代理對象
public static Object getProxy(Object target) {
PigInvocationHandler handler = new PigInvocationHandler();
// 爲handler設置target對象
handler.setTarget(target);
// 建立並返回一個動態代理
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);
}
public static void main(String[] args) throws Exception {
// 建立一個原始的FatPig對象,做爲target
Pig target = new FatPig();
// 以指定的target來建立動態代理對象
Pig pig = (Pig) MyProxyFactory.getProxy(target);
pig.info();
pig.run();
}
}
複製代碼
運行結果:
==== 方法開始執行 ====
我是一頭小肥豬!
==== 方法執行結束 ====
==== 方法開始執行 ====
我要跑步啦!
==== 方法執行結束 ====
上面實現了簡單的AOP功能,咱們能夠在invoke方法裏面加上更多的判斷,使得功能更增強大,例如能夠根據method參數指定某些方法先後執行特殊的處理。