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