本文译自博文 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
现在来简单解释一下。呵呵,道理请见前一篇博文。