代理与动态代理 阅读think in java所得(2)

代理是基本的设计模式之一,是你为了提供额外的或者不同的操作,而插入的用来代替“实际”对象的对象。

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

View Code
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);
	}
	
}

  

原文地址:https://www.cnblogs.com/nextStep/p/2565490.html