Java 动态代理

代理是基本的设计模式之一,作用是为了提供额外的或不同的操作,而插入的用来代替“实际”对象的对象。这些操作通常涉及与“实际”对象的通信,因此代理通常充当着中间人的角色,下面是一个代理结构的例子:

先定义一个接口:

public interface Interface {
	void doSomething();
	void somethingElse(String arg);
}
class RealObject implements Interface{

	@Override
	public void doSomething() {
		System.out.println("doSomething()");		
	}

	@Override
	public void somethingElse(String arg) {
		System.out.println("somethingElse():" + arg);
		
	}	
}

再定义一个类来实现接口和重写该接口里的方法:

public class SimpleProxy implements Interface {
	private Interface proxied;
	public SimpleProxy(Interface proxied) {
		this.proxied = proxied;
	}
	@Override
	public void doSomething() {
		System.out.println("SimpleProxy doSomething()");	
		proxied.doSomething();
	}

	@Override
	public void somethingElse(String arg) {
		System.out.println("SimpleProxy somethingElse():" + arg );
		proxied.somethingElse(arg);
	}
}

再定义一个方法来调用接口和类:

public class Demo {
	public static void consumer(Interface iface) {
		iface.doSomething();
		iface.somethingElse("Hey");
	}
	public static void main(String[] args) {
		consumer(new RealObject());
		consumer(new SimpleProxy(new RealObject()));
	}
}

输出结果:Java 动态代理

因为consumer()接受的Interface,所以无法知道正在获得的到底是RealObject还是SimpleProxy,因为二者都是实现了Interface,但是SimpleProxy已经被插入到了客户端和RealObject之间,因此它会执行操作,然后调用了RealObject上相同的方法。

而Java的动态代理可以动态地创建代理并动态地处理对所代理方法的调用。在动态代理上所做的所有调用都会被重定向到单一的调用处理器上,揭示调用的类型并确定相应的对策,如动态代理重写Demo:

public class Dynamic  implements InvocationHandler{
	private Object proxied;
	public Dynamic(Object proxied) {
		this.proxied = proxied;
	}
	@Override
	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 object : args) {
				System.out.println("   " + object);
			}			
		}
		return method.invoke(proxied, args);		
	}	
}


public class Demo2 {
	public static void consumer(Interface iface) {
		iface.doSomething();
		iface.somethingElse("Hey");
	}
	public static void main(String[] args) {
		RealObject real = new RealObject();
		consumer(real);
		Interface proxy = (Interface)Proxy.newProxyInstance(
				Interface.class.getClassLoader(),
				new Class[] {Interface.class}, 
				new Dynamic(real));
		consumer(proxy);
	}
}

输出结果:

Java 动态代理

通过调用静态方法Proxy.newProxyInstance()可以创建动态代理,这个方法需要得到一个类加载器,通常可以从已经被加载的对象中获取其类加载器,然后传递给它,该代理实现的接口列表(不是类或抽象类),以及InvocationHandler接口的一个实现。动态代理可以将所有调用重定向到调用处理器,因此通常会向调用处理器的构造器传递给一个“实际”对象的引用,从而使得调用处理器在执行其中介任务时,可以请求转发。