本文譯自博文 Understanding Java Dynamic Proxy
假定,我們需要一個計算機,就把這個介面叫做Calculator吧。
interface Calculator { public int add(int a, int b); public int sub(int a, int b);}
有了介面,我們還需要一個真正的計算機實現,就把它叫做CalculatorImpl吧
public class CalculatorImpl implements Calculator { public int add(int a,int b) { int c = a + b; System.out.println("[TARGET METHOD CALL (add)] Result is " + c); return c; } @Override public int sub(int a, int b) { int c = a - b; System.out.println("[TARGET METHOD CALL (sub)] Result is " + c); return c; }}
這個計算機的代碼很直觀。
OK,新需求來了,雖然做加法和做減法的核心業務不用需要改變,但是我們希望在進行加減之前能夠列印出日誌。同時,目前已經有其他代碼在利用Calculator介面和CalculatorImpl類了,我們也特麼不想影響這些已有的代碼。咋辦呢?來吧,試試動態代理類
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.util.Arrays; public class LoggingValidationHandler implements InvocationHandler{ private Object target; public LoggingValidationHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("[BEFORE METHOD CALL] The method " + method.getName() + "() begins with "+ Arrays.toString(args)); Object result = method.invoke(target, args); System.out.println("[AFTER METHOD CALL ] The method " + method.getName() + "() ends with " + result.toString()); return result; }}
import java.lang.reflect.Proxy;public class Clinet4 {public static void main(String[] args) {Calculator plainCalculator = new CalculatorImpl();Calculator proxiedCalculator = (Calculator) Proxy.newProxyInstance(plainCalculator.getClass().getClassLoader(),plainCalculator.getClass().getInterfaces(),new LoggingValidationHandler(plainCalculator));proxiedCalculator.add(10, 6);System.out.println("--------------------------------------------------------------------");proxiedCalculator.sub(10, 6);}}
運行,輸出為
[BEFORE METHOD CALL] The method add() begins with [10, 6][TARGET METHOD CALL (add)] Result is 16[AFTER METHOD CALL ] The method add() ends with 16--------------------------------------------------------------------[BEFORE METHOD CALL] The method sub() begins with [10, 6][TARGET METHOD CALL (sub)] Result is 4[AFTER METHOD CALL ] The method sub() ends with 4
現在來簡單解釋一下。呵呵,道理請見前一篇博文。