java 有一个动态代理的功能,它允许在 java 运行过程中,基于一个类动态产生另一个 java 类,此类是代理类,任何对前者里面的某个方法的调用可以通过代理类的调用来完成,这就是“代理”的作用。举例如下:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface MyInteger
{
public void say();
}
class MyInterImpl implements MyInteger
{
private int _value;
public MyInterImpl(int i ) {
_value = i;
}
@Override
public void say() {
System.out.println("_value : " + _value);
}
}
public class ProxyTest
{
public static void main(String[] args)
{
MyInteger[] elements = new MyInteger[10];
for (int i = 0; i < elements.length; i++)
{
MyInterImpl value = new MyInterImpl(i + 1);
Class[] interfaces = value.getClass().getInterfaces();
InvocationHandler handler = new TraceHandler(value);
try{
elements[i] = (MyInteger)Proxy.newProxyInstance(MyInteger.class.getClassLoader(),
interfaces, handler);
}
catch(Exception ex)
{
ex.printStackTrace();
throw ex;
}
}
for(MyInteger o : elements)
{
o.say(); //任何在 MyInteger 上的调用均会被先定向到代理类的 invoke 方法上
}
}
}
/**
An invocation handler that prints out the method name
and parameters, then invokes the original method
*/
class TraceHandler implements InvocationHandler
{
/**
Constructs a TraceHandler
@param t the implicit parameter of the method call
*/
public TraceHandler(Object t)
{
target = t;
}
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable//此方法在代理类中
{ //的方法被调用时均会被调用
// print implicit argument
System.out.print(target);
// print method name
System.out.print("." + m.getName() + "(");
// print explicit arguments
if (args != null)
{
for (int i = 0; i < args.length; i++)
{
System.out.print(args[i]);
if (i < args.length - 1)
System.out.print(", ");
}
}
System.out.println(")");
//调用实际的方法
return m.invoke(target, args);
}
private Object target;
}
这是个非常有用的特性,我们可以利用这个特性在运行期动态替换掉某种具体的实现,或者针对于某种接口产生具体的实现。更进一步,它还允许我们在某一环境下使用一种实现,另一环境下使用另一实现,如对测试环境和生产环境的区分有不同的程序逻辑。