如何实现JDK动态代理与Cglib动态代理

 

一、JDK动态代理

      通过使用Proxy和InvocationHandler 来动态创建对象的方式。

        Proxy:提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。

       一般我们通过JDK动态代理是通过下面这个方法。

Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

这里简单解释一下参数的意思:

      ClassLoader loader : 类加载器

      Class<?>[] interfaces : 目标对象实现的接口类型

      InvocationHandler h : 执行目标对象的方法时,会触发事情处理器方法, 会把当前执行的目标对象方法作为参数传入。

举个栗子:


public class JDKProxy implements InvocationHandler {
/**
 * Proxy提供用于创建动态代理类和代理对象的静态方法,它也是所有动态代理类的父类。
 * 如果我们在程序中为一个或多个接口动态地生成实现类,就可以使用Proxy来创建动态代理类:
 * 如果需要为一个或多个接口动态地创建实例,也可以使用Proxy来创建动态代理实例。
 * Proxy提供了如下两个方法来创建动态代理类和动态代理实例:
 */
	/**
	 * 要代理的对象
	 */
	private Object subject;

	public JDKProxy(Object subject) {
		this.subject = subject;
	}

	/**
	 * 重写invoke 方法
	 * @param proxy  代理对象
	 * @param method  需要增强的方法
	 * @param args  方法需要的参数
	 * @return
	 * @throws Throwable
	 */
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("JDK 动态代理:查询之前的校验逻辑......");
		Object invoke = method.invoke(subject, args);
		System.out.println("JDK 动态代理:查询之后的校验逻辑......");
		return invoke;
	}

	public static void main(String[] args) {
		P person = new Person();
		P p = (P)Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), new JDKProxy(person));
		p.query();
		/**
		 * 总结一下,一共分为以下四步
		 * 1、通过实现 InvocationHandler 接口创建自己的调用处理器;
		 * 2、通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
		 * 3、通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
		 * 4、通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
		 */
	}

}


interface P{
	public void query();
}

class Person implements P{

	public void query(){
		System.out.println("我在找东西。。。。。。");
	}

}

输出结果是:

这些就能动态在执行方法前后做一些自己的业务逻辑。

 

二、CGLIB动态代理

       Cglib代理也叫做子类代理,是通过继承的方式对目标对象进行功能扩展

      


public class MyMethodInterceptor implements MethodInterceptor {

	/**
	 * CGLIB 增强类对象,代理类对象是由 Enhancer 类创建的,
	 * Enhancer 是 CGLIB 的字节码增强器,可以很方便的对类进行拓展
	 */
	private Enhancer enhancer = new Enhancer();

	/**
	 *
	 * @param o 被代理的对象
	 * @param method 代理的方法
	 * @param args 参数
	 * @param methodProxy CGLIB产生的代理对象
	 * @return cglib生成用来代替Method对象的一个对象,使用MethodProxy比调用JDK自身的Method直接执行方法效率会有提升
	 * @throws Throwable
	 */
	public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		System.out.println("CGLIB 被代理之前");
		methodProxy.invokeSuper(o,args);
		System.out.println("CGLIB 被代理之后");
		return null;
	}

	public Object newProxyInstance(Class<?> c){
		/**
		 * 设置产生的代理对象的父类,增强类型
		 */
		enhancer.setSuperclass(c);
		/**
		 * 定义代理逻辑对象为当前对象,要求当前对象实现 MethodInterceptor 接口
		 */
		enhancer.setCallback(this);
		/**
		 * 使用默认无参数的构造函数创建目标对象,这是一个前提,被代理的类要提供无参构造方法
		 */
		return enhancer.create();
	}


}

class TestCglib{

	public static void main(String[] args) {

		MyMethodInterceptor cglib = new MyMethodInterceptor();
		Animal o = (Animal)cglib.newProxyInstance(Animal.class);
		o.query();
	}

}

class Animal{
	public void query(){
		System.out.println("大象在喝水......");
	}
}

 执行结果如图所示

 

因为Cglib是通过继承的方式创建动态代理,所以说被代理的对象不能是被final修改时类,否则会报java.lang.IllegalArgumentException:

目标对象的方法如果为 final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.

 

 

当了解了动态代理之后,可以想一想Mybatis是用的哪种代理。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小tu豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值