Java设计模式学习笔记:代理模式(三)

上一篇文章介绍了通过JDKProxy的方式,将之前的静态代理转换为动态代理,传送门如下:

Java设计模式学习笔记:代理模式(二)

今天继续研究动态代理的另外一种形式,通过Cglib实现动态代理,Cglib是针对类来实现代理的,他的原理是对代理的目标类生成一个子类,并覆盖其中方法来实现增强,因为底层是基于创建被代理类的一个子类,所以它避免了JDK动态代理类的缺陷(被代理类必须要实现接口,JDK动态代理重要特点是代理接口)。但因为采用的是继承,所以不能对final修饰的类进行代理,因为final修饰的类不可继承。

通过Cglib实现动态代理,首先需要引入Cglib包:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib-nodep</artifactId>
    <version>2.2</version>
</dependency>

我们还是以找对象这个例子来说明,首先是被代理对象:

package com.rq.pattern.proxy.dynamicproxy.cglibproxy;

/**
  * Title: WangWu
  * Description: 
  * @author RQ 
  * @date 2020年3月30日
 */
public class WangWu {

	/**
	 * 王五找老婆
	 */
	public void findLove() {
		
		System.out.println("王五找老婆要求:身轻体柔易推倒");
	}

}

可以看到,被代理对象是不需要实现接口的,接下来就是实现代理的类:

package com.rq.pattern.proxy.dynamicproxy.cglibproxy;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
  * Title: CglibMeiPo
  * Description: 中介媒婆
  * @author RQ 
  * @date 2020年3月30日
 */
public class CglibMeiPo implements MethodInterceptor{

	public Object getInstance(Class<?> clazz) {
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(clazz);
		enhancer.setCallback(this);
		return enhancer.create();
	}

	private void before() {
		System.out.println("中介媒婆收到相关需求,开始寻找资源");
	}
	
	private void after() {
		System.out.println("相亲完成后,双方来电,开始交往");
	}

	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		before();
		Object result = proxy.invokeSuper(obj, args);
		after();
		return result;
	}
}

通过Cglib实现动态代理,核心是实现MethodInterceptor接口,并重写intercept()方法,Cglib生成代理类时,是通过Enhancer类实现的,入参是被代理类,因为动态生成的类是被代理类的子类,所以我们设置目标类为生成类的父类,enhancer.setSuperclass(clazz);其他的步骤都是Cglib中约定好的步骤,约定俗成。

如果想要针对动态生成的类做增强,我们可以将增强部分的代码写在intercept()方法中,该方法会被动态代理生成的类自动调用,例如在上面例子中的before()、after()方法都是针对生成类的增强。

看一下通过Cglib动态代理的具体使用方法:

package com.rq.pattern.proxy;

import com.rq.pattern.proxy.dynamicproxy.cglibproxy.CglibMeiPo;
import com.rq.pattern.proxy.dynamicproxy.cglibproxy.WangWu;

/**
  * Title: CglibProxyTest
  * Description: Cglib测试
  * @author RQ 
  * @date 2020年3月30日
 */
public class CglibProxyTest {

	public static void main(String[] args) {
		
		CglibMeiPo meipo = new CglibMeiPo();
		WangWu wangWu = (WangWu) meipo.getInstance(WangWu.class);
		wangWu.findLove();
	}
}

运行结果如下:

中介媒婆收到相关需求,开始寻找资源
王五找老婆要求:身轻体柔易推倒
相亲完成后,双方来电,开始交往

静态代理、JDK方式动态代理、Cglib方式动态代理比较如下:

1、静态代理在编译时产生class字节码文件,可以直接使用,效率高。

2、JDK动态代理必须实现InvocationHandler接口,通过invoke调用被委托类接口方法是通过反射方式,比较消耗系统性能,但可以减少代理类的数量,使用更灵活。

3、Cglib代理无需实现接口,通过生成类字节码实现代理,比反射稍快,不存在性能问题,但cglib会继承目标对象,需要重写方法,所以目标对象不能为final类。

以上是在学习动态代理模式中的学习心得,欢迎相互学习讨论。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值