Java动态代理及原理

代理模式应该都不陌生。

Java通过反射机制,提供了代理模式的实现。其使用到的核心类如下:InvocationHandler接口  Proxy类

先看示例:

接口:

public interface MyInterface {
	void method();
}

接口实现类:

public class MyInterfaceImpl implements MyInterface {

	public void method() {
		System.out.println("method");
	}

}
代理类:
public class MyProxy implements InvocationHandler {

	Object obj;

	public ProxyClass(Object o) {
		obj = o;
	}

	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object result = null;
		try {
			System.out.println("before the method is called ");
			result = method.invoke(obj, args);
		} catch (Exception e) {
		} finally {
			System.out.println("after the method is called");
		}
		return result;
	}
}

调用类:

public class Main {
	public static void main(String[] argv) throws Exception {
		MyInterface myintf = (MyInterface) Proxy.newProxyInstance(                                                1
				MyInterface.class.getClassLoader(),
				new Class[] { MyInterface.class }, new MyProxy(                                           2
						new MyInterfaceImpl()));
		System.out.println(myintf instanceof Proxy);

		myintf.method();                                               
	}
}

需要关注的是代理类的实现。自JDK1.3之后,每一个代理的实例会有一个InvocationHandler对应。当代理实例的方法被调用的时候,改方法将会被编译并且发送到对应的InvocationHandler的invoke方法上。

这里需要注意两处代码:

1. new ProxyClass(new MyInterfaceImpl()) 对应MyProxy中的 result = method.invoke(obj, args); 该处很简单,就是对实际方法的调用执行。

2.Proxy.newProxyInstance


先看参数:1.ClassLoader loader 代理类的加载体 2. Class<?>[] interfaces 代理类的继承接口。3 InvocationHandler h 上面的MyProxy

代理类的集成接口,这里有多个的原因,是因为一个类可能会实现多个接口。


接下来:

Class cl = getProxyClass(loader, interfaces);

通过loader和interfaces创建代理类。具体方法如下:

 try {
		interfaceClass = Class.forName(interfaceName, false, loader);
	    } catch (ClassNotFoundException e) {
	    }

Proxy.class

接下来进行缓存处理:

synchronized (loaderToCache) {
	    cache = (Map) loaderToCache.get(loader);
	    if (cache == null) {
		cache = new HashMap();
		loaderToCache.put(loader, cache);
	    }
最后,返回已经创建的接口。


当创建好这个接口之后,JDK所作的是   Constructor cons = cl.getConstructor(constructorParams);  而这个constructorParams是什么,这个constructorParams就是InvocationHandler.class 就是说所有Proxy的实现方法的接口。

在这里,便得到了Constructor 然后再通过newInstance去得到这个代理的实类。


在这里应该比较明白了,所谓的代理,在1处创建的是Proxy的对象,而这个Object继承的接口则是MyInterface,当然了,运行方法还是为定义的method,只不过是,创建代理的时候,就已经将method包装,实际上执行的只不过为invoke中的方法罢了。


至于Proxy使用场景:无非就是对前置有验证或者类似的一半情况了。Spring的interceptor就是用的这种模式,但是javaee的filter用的不是这种模式,是回调模式。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章