代理是基本的设计模式之一,是你为了提供额外的或者不同的操作,而插入的用来代替“实际”对象的对象。
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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
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);
}
}