动态代理

动态代理

  • 在程序运行时,创建代理类的代理方式被称为动态代理
  • 分类:
    • jdk动态代理是利用java反射机制(java.lang.reflect包)
    • cglib动态代理底层则是借助asm来实现的
  • 好处:
    • 在不改变程序源码的基础上,对代码进行增强或者屏蔽
  • 动态代理的前提:必须有接口

JDK动态代理

原理

入门

  • 接口
public interface Sing {

	public abstract void sing();
	
}
  • 被代理类 
public class Singer implements Sing {

	@Override
	public void sing() {
		System.out.println("XXX歌手唱歌");
	}

}
  • 代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {

	private Sing obj;

	public MyInvocationHandler() {
		super();
	}

	public MyInvocationHandler(Sing obj) {
		super();
		this.obj = obj;
	}

	/*
	 * Object proxy:代理类对象,和我们无关
	 * method:要增强的方法对象:sing() 
	 * Object[] args:增强的方法需要的参数,没有忽略
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        // 调用没有增强之前的方法
		Object result = method.invoke(obj, args);

		System.out.println("跳舞");

		System.out.println("捐款");
		
		return result;// 原来的方法返回什么,这里还返回什么
	}

}
  • 测试类
import java.lang.reflect.Proxy;

public class Demo01_Proxy {

	public static void main(String[] args) {

		Sing singer = new Singer();
		System.out.println("*******************代理之前的方法*******************");
		singer.sing();

		System.out.println("*******************代理之后的方法*******************");
		singer = myProxy(singer);
		singer.sing();
	}

	private static Sing myProxy(Sing singer) {
		// 获取被代理类的类加载器
		ClassLoader loader = Singer.class.getClassLoader();
		// 获取被代理类实现的接口列表
		Class<?>[] interfaces = Singer.class.getInterfaces();
		/*
		 * ClassLoader loader:被代理类的类加载器 
		 * Class<?>[] interfaces:被代理类实现的接口列表
		 * java.lang.reflect.InvocationHandler h
		 */
		singer = (Sing) Proxy.newProxyInstance(loader, interfaces, new MyInvocationHandler(singer));
		return singer;
	}
}
  •  执行结果

案例

案例1

  • 题目:求任意一个方法的运行时间
  • 接口
public interface RunCode {

	public abstract void run();
}
  • 被代理类
public class Demo01 implements RunCode {

	@Override
	public void run() {
		int sum = 0;
		for (int i = 0; i < 1000; i++) {
			sum += i;
		}
		System.out.println("0-1000的和:"+sum);
	}
}
  • 代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {

	private RunCode obj;

	public MyInvocationHandler() {
		super();
	}

	public MyInvocationHandler(RunCode obj) {
		super();
		this.obj = obj;
	}

	/*
	 * Object proxy:代理类对象,和我们无关 Method
	 * method:要增强的方法对象:sing()---->getMethod("sing"); Object[] args:增强的方法需要的参数
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

		Long t1 = System.currentTimeMillis();
		
		// 调用没有增强之前的方法
		Object result = method.invoke(obj, args);
		
		Long t2 = System.currentTimeMillis();
		
		System.out.println("消耗时间" + (t2 - t1)+"毫秒");

		return result;// 原来的方法返回什么,这里还返回什么
	}

}
  • 测试类
import java.lang.reflect.Proxy;

public class TestDemo {

	public static void main(String[] args) {
		// 1.创建被代理类对象
		RunCode rc = new Demo01();

		rc = myProxy(rc);
		rc.run();
	}

	private static RunCode myProxy(RunCode rc) {
		RunCode proxyRc = (RunCode) Proxy.newProxyInstance(rc.getClass().getClassLoader(),
				rc.getClass().getInterfaces(), 
				new MyInvocationHandler(rc));
		return proxyRc;
	}
}
  • 执行结果

 案例2

  • 模拟Collections中的:public static <T> List<T> unmodifiableList(List<? extends T> list)
  • 方法使用案例
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Demo01Proxy {

	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		list.add("hello");
		list.add("java");
		list = Collections.unmodifiableList(list);
		//list.add("world");// java.lang.UnsupportedOperationException
		//list.remove("hello");// java.lang.UnsupportedOperationException
		System.out.println(list.size());
	}
}
  • 动态代理实现
    • 接口(不用写,使用java.util.List)
    • 被代理类(不用写,使用java.util.ArrayList)
    • 代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;

public class MyInvocationHandler<T> implements InvocationHandler {

	private List<T> obj;

	public MyInvocationHandler() {
		super();
	}

	public MyInvocationHandler(List<T> obj) {
		super();
		this.obj = obj;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

		// 抛出运行时异常
		if (method.getName().equals("add")) {
			throw new RuntimeException("add方法不可用");
		}
		if (method.getName().equals("remove")) {
			throw new RuntimeException("remove方法不可用");
		}
		if (method.getName().equals("set")) {
			throw new RuntimeException("set方法不可用");
		}
		// 如果是其他方法,直接调用
		Object result = method.invoke(obj, args);

		return result;
	}

}
  • 测试类
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

public class TestDemo {

	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		list.add("hello");
		list.add("world");
		// 使用动态代理
		list = myProxy(list);
		// list.add("world");//java.lang.RuntimeException: add方法不可用
		System.out.println(list.size());
	}

	private static <T> List<T> myProxy(final List<T> list) {
		@SuppressWarnings("unchecked")
		List<T> proxyList = (List<T>) Proxy.newProxyInstance(list.getClass().getClassLoader(),
				list.getClass().getInterfaces(), new MyInvocationHandler<T>(list));
		return proxyList;
	}
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值