代理是基本的设计模式之一,是你为了提供额外的或者不同的操作,而插入的用来代替“实际”对象的对象。
ProxyDemo.java:
import java.lang.reflect.Proxy; interface Animal{ void eat(); } class Dog implements Animal{ public void eat() { System.out.println( "Dog's eat...." ); } } class ProxyClient implements Animal{ private Animal animalProxy; ProxyClient( Animal animal ){ animalProxy = animal; } public void eat() { System.out.println( "animal wash hands first...." ); animalProxy.eat(); } } public class ProxyDemo { public static void consumer( Animal animal ){ animal.eat } public static void main( String[] args ){ consumer( new ProxyClient( new Dog() ) ) } }
动态代理:可以动态的创建代理,并动态的处理对所代理方法的调用。在动态代理上所做的所有调用都会被重定向到单一的调用处理器上,它的工作是揭示调用的类型并确定相应的对策。
下面DynamicProxyDemo.java用动态代理重写ProxyDemo.java

interface Animal{ void eat(); } class Dog implements Animal{ public void eat() { System.out.println( "Dog's eat...." ); } } class DynamicProxyHandler implements InvocationHandler{ private Object proxied; DynamicProxyHandler( Object proxied ){ this.proxied = proxied; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println( "proxy:"+proxy.getClass()+" ,method: "+method+" ,args: "+args ); if( args != null){ for( Object arg : args ){ System.out.println(" "+arg); } } return method.invoke( proxied, args ); } } public class DynamicProxyDemo { public static void consumer( Animal animal ){ animal.eat(); } public static void main( String[] args ){ Animal proxy = ( Animal )Proxy.newProxyInstance( Animal.class.getClassLoader() , new Class[]{ Animal.class }, new DynamicProxyHandler( new Dog() )); consumer(proxy); } }
通过调用静态方法Proxy.newProxyInstance()可以创建动态代理,这个方法需要一个类加载器,一个你希望该代理实现的接口列表,以及一个InvocationHandler接口的实现。
invoke()中传递进来了代理对象,以防你需要区分请求的来源,在其内部,在代理上调用方法时要格外当心,因为对接口的调用会被重定向为对代理的调用。
通常,你会执行被代理的操作,然后使用Method.invoke()将请求转发给被代理对象,并传入必须的参数。但是你可以通过传递其他的参数,来过滤某些方法调用。代码如下:
class MethodSelector implements InvocationHandler{ private Object proxied; public MethodSelector( Object proxied ){ this.proxied = proxied ; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if( method.getName().equals( "eat" ) ){ System.out.println( "proxy detected the interesting method" ); } return method.invoke( proxied , args); } }