什么是静态代理和动态代理

本文介绍了如何使用Java代理模式来统计接口方法的执行时间,以减少代码冗余并增强代码结构。首先展示了静态代理的实现,然后通过动态代理优化,避免了为每个接口实现重复的代理代码。动态代理利用`InvocationHandler`接口和`Proxy`类,能灵活地对多个接口实例进行方法耗时的统计。示例中展示了动态代理在统计`Dongwu`接口实现类方法执行时间的应用。
摘要由CSDN通过智能技术生成

当实现同一个接口的很多类需要进行同样的操作,我们需要重复写很多代码,这个时候我们可以使用代理模式,减少代码的冗余,增加代码的层次感。比如我们需要统计一个接口的运行时间:

         接口类

public interface Dongwu {
	
	 public  void  eat(String str);
	  public void  drink(String str);
	  public void play(String str);
	  
	     

}

          实现类

 

public class Dogs implements Dongwu{

	@Override
	public void eat(String str) {
		System.out.println("一只狗在吃狗粮【"+str+"】");
		
	}

	@Override
	public void drink(String str) {
		System.out.println("一只狗在喝水【"+str+"】");
	}

	@Override
	public void play(String str) {
		System.out.println("一只狗在玩球【"+str+"】");
	}

}



public class Pig implements Dongwu{

	@Override
	public void eat(String str) {
		System.out.println("一只猪在吃猪食【"+str+"】");
		
	}

	@Override
	public void drink(String str) {
		System.out.println("一只猪喝水【"+str+"】");
		
	}

	@Override
	public void play(String str) {
		System.out.println("一只猪玩球【"+str+"】");
		
	}

}

   代理类

   


/**
 * 动物接口静态代理类
 * @author 
 *
 */
public class DongWuProxy implements Dongwu{
	
	public Dongwu dw;

	public DongWuProxy(Dongwu dw) {
		super();
		this.dw = dw;
	}

	@Override
	public void eat(String str) {
		long starTime = System.nanoTime();
		dw.eat(str);
		long endTime = System.nanoTime();
		System.out.println("方法耗时(纳秒):" + (endTime - starTime));

	}

	@Override
	public void drink(String str) {
		long starTime = System.nanoTime();
		dw.drink(str);
		long endTime = System.nanoTime();
		System.out.println("方法耗时(纳秒):" + (endTime - starTime));

	}

	@Override
	public void play(String str) {
		long starTime = System.nanoTime();
		dw.play(str);
		long endTime = System.nanoTime();
		System.out.println("方法耗时(纳秒):" + (endTime - starTime));

	}
	
	
}

 测试类

   

public class DongwuTest {



	public static void main(String[] args) {
		DongWuProxy d = new DongWuProxy(new Pig());
		d.drink("小猪1号");

		DongWuProxy dd = new DongWuProxy(new Dogs());
		dd.drink("小猪2号");

	

	}
	
		
		
}

一只猪喝水【小猪1号】
方法耗时(纳秒):449400
一只狗在喝水【小猪2号】
方法耗时(纳秒):120300

    当我们接口很多的时候,我们就需要写很多代理类而且得写很多代理方法,这个时候我们就需要用到动态代理来优化替代。

    我们经常使用的框架如spring mybatis status 等都用到了动态代理

   动态代理类

    

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class CostInvocationTimeHandler implements InvocationHandler{
	
	private Object target;

	public CostInvocationTimeHandler(Object target) {
		this.target = target;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		long starTime = System.nanoTime();
		Object result = method.invoke(this.target, args);// @1
		long endTime = System.nanoTime();
		System.out.println( "方法耗时(纳秒):" + (endTime - starTime));
		return result;
	}

	/**
	 * 用来创建targetInterface接口的代理对象
	 *
	 * @param target
	 *            需要被代理的对象
	 * @param targetInterface
	 *            被代理的接口
	 * @param <T>
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T createProxy(Object target, Class<T> targetInterface) throws Throwable {
		if (!targetInterface.isInterface()) {
			throw new IllegalStateException("targetInterface必须是接口类型!");
		} else if (!targetInterface.isAssignableFrom(target.getClass())) {
			throw new IllegalStateException("target必须是targetInterface接口的实现类!");
		}
		return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
				new CostInvocationTimeHandler(target));
	}

}

    测试类

  


public class DongwuTest {

	private Pig p = new Pig();

	public static void main(String[] args) {
	
		DongwuTest d = new DongwuTest();
		d.test();

	}

	void test() {

		Dongwu d;
		try {
			d = CostInvocationTimeHandler.createProxy(p, Dongwu.class);
			d.drink("小猪1号");
			d.eat("小猪2号");
			d.play("小猪3号");
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}

一只猪喝水【小猪1号】
方法耗时(纳秒):459600
一只猪在吃猪食【小猪2号】
方法耗时(纳秒):37500
一只猪玩球【小猪3号】
方法耗时(纳秒):73400

代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。

因为代理类继承了InvocationHandler,根据继承机制,不能再有父类,所以动态代理只能对接口代理。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值