动态代理

所谓动态代理,就是提供一个接口给Proxy类,Proxy类会在运行时自己实现该接口,然后返回该接口的实例,之后对该接口方法的调用都会传给一个处理类处理。它实际上动态实现了该接口,但在方法的实现中,会将该方法传递给了处理器(handler)的处理函数(invoke)。

和动态代理相关的类

Proxy

提供了静态方法创建动态代理类(dynamic proxy class)和实例(instance),也是所有被该类方法创建的动态代理类的父类。

调用getInvocationHandler方法可得到调用处理器( invocation handler),getProxyClass可得到动态代理类的Class对象,newProxyInstance可以创建代理实例(proxy instance)。

InvocationHandler

调用处理器要实现的接口,代理实例被调用的方法会传入该接口的invoke方法中。

相关名词

动态代理类(dynamic proxy class):运行时动态创建的类,实现了传入的接口,可通过Proxy.getProxyClass获得。

代理实例:动态代理类的对象,可由Proxy.newProxyInstance获得。

调用处理器(invocation handler):实现了InvocationHandler的类,动态代理调用的方法都会被出给该类处理。

代码

下面给出具体代码,该代码可以代理任意一个类, 然后计算每个方法被调用所花的时间。

public class App 
{
	public static void main(String[] arg) {
		//创建代理对象,传入Map接口
		Map<String,String> mapProxyInstance=(Map)Proxy.newProxyInstance(App.class.getClassLoader(),new Class[] {Map.class},
				new TimingDynamicInvocationHandler(new HashMap<>()));
		//调用接口Map的方法
		mapProxyInstance.put("hello", "world");
		System.out.println(mapProxyInstance.get("hello"));
		System.out.println(mapProxyInstance instanceof Proxy);
	}
	
	/**
	 * 处理类的实现
	 * @author Administrator
	 *
	 */
	 static class TimingDynamicInvocationHandler implements InvocationHandler {
		 
	
	     //用于存放target的方法名和Method类的信息。
	    private final Map<String, Method> methods = new HashMap<>();
	    //被代理的对象,也就是真实对象(real object)
	    private Object target;
	 
	    /**
	     * 传入被代理的对象,将它的所有方法名都记录下来
	     * @param target 真实对象
	     */
	    public TimingDynamicInvocationHandler(Object target) {
	        this.target = target;
	 
	        for(Method method: target.getClass().getDeclaredMethods()) {
	            this.methods.put(method.getName(), method);
	        }
	    }
	 
	    
	    @Override
	    public Object invoke(Object proxy, Method method, Object[] args) 
	      throws Throwable {
	    	//对每一次方法的调用都记录所用时长
	        long start = System.nanoTime();
	        //通过被调用方法的方法名获取Method对象,然后调用真实对象的方法
	        Object result = methods.get(method.getName()).invoke(target, args);
	        long elapsed = System.nanoTime() - start;
	 
	        System.out.println("excecuting "+method.getName()+":"+elapsed+"ns");
	        return result;
	    }
	}
	
}

输出:

excecuting put:179980ns
excecuting get:8430ns
world
true

参考:

https://www.baeldung.com/java-dynamic-proxies

http://tutorials.jenkov.com/java-reflection/dynamic-proxies.html

https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Proxy.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值