示例:
public class InstanceProxyUtils { //被代理的對象 public static class T { public void f() { System.out.println("測試"); } } public static class TMethodInvokeInterceptor implements MethodInterceptor { /** * 1. 代理對象的類是被代理類的子類 * <p> * 2. 代理對象重寫了父類的所有方法 * 重寫的結果時:調用代理對象的任何方法都會觸發MethodInterceptor.intercept * <p> * 3. 當調用代理對象的方法時會將 代理對象自身/真實方法/調用參數/代理方法(調用時直接觸發的方法,代理對象對父類方法的重寫) 封裝起來作爲MethodInterceptor.intercept方法的入參 * <p> * 4. method.invoke(真實對象,params) 等價於 methodProxy.invokeSuper(代理對象,params) * <p> * 5. 注意:第一個參數(代理對象)慎用 * 5.1 切勿在MethodInterceptor.intercept方法中調用第一個參數proxy的任何方法,會引發無限遞歸最終OOM * proxy.toString->MethodInterceptor.intercept->proxy.toString->MethodInterceptor.intercept->...... * * @param proxy 代理對象 * @param method 被代理的類中的真實方法 * @param objects 調用時傳入的參數 * @param methodProxy 代理對象中的代理方法 * @return 方法返回值 */ @Override public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { //這樣也是允許的,等價於 method.invoke(new T(), objects); methodProxy.invoke(new T(), objects); //這樣調用是允許的 methodProxy.invokeSuper(proxy, objects); //這樣調用是不允許的,將會報強轉異常,方法中會嘗試將第一個參數強轉爲代理對象 //methodProxy.invokeSuper(new T(), objects); //這樣會導致無限遞歸 method.invoke(proxy, objects)->MethodInterceptor.intercept->method.invoke(proxy, objects)->MethodInterceptor.intercept->.... //method.invoke(proxy, objects); //這樣將會導致無限遞歸,原因和method.invoke(proxy, objects);相同 //methodProxy.invoke(proxy, objects); return null; } } public static void main(String[] args) { //代理對象的構建器 Enhancer enhancer = new Enhancer(); //設置代理對象的父類 enhancer.setSuperclass(T.class); //設置代理對象方法回調 enhancer.setCallback(new TMethodInvokeInterceptor()); //構建代理對象 T o = (T) enhancer.create(); o.f(); } }
幾點疑問的解答:
1. 代理對象是否必須指向一個被代理對象?
否!根據實際需求,可以自定義攔截後的相關邏輯。