JAVA代理模式-cglib动态代理的实现(三)

本文详细介绍了CGLIB动态代理在JAVA代理模式中的应用,当无接口时作为JDK动态代理的补充。讲解了如何通过CGLIB库创建代理类,动态生成目标类的子类,并在代理对象调用方法时插入额外操作。内容包括引入CGLIB库、创建实体类、代理工厂类的实现以及客户端调用示例。
摘要由CSDN通过智能技术生成

传送门:JAVA代理模式-静态代理的实现(一)
JAVA代理模式-JDK动态代理的实现(二)
JAVA代理模式-cglib动态代理的实现(三)
JAVA代理模式-三种代理模式的对比(四)

代理模式简介、静态代理、JDK动态代理可以参考以下文章:
JAVA代理模式-静态代理的实现(一)
JAVA代理模式-JDK动态代理的实现(二)

CGLIB动态代理:

在之前JAVA代理模式-静态代理的实现(一)JAVA代理模式-JDK动态代理的实现(二)中,实现代理模式时,首先需要定义一个接口,然后定义实现该接口的实现类,以及获得实现该接口的代理类。

但是如果没有定义接口,只定义了实体类。很显然JDK代理是无法使用了,因为JDK动态代理要求必须定义接口,对接口进行代理。这时,我们就可以使用CGLIB动态代理来实现。

CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。但是使用CGLIB需要自行进行导包。

考虑以下场景,你需要去中介手里买电影票,中介会在售票的基础上增强手续费。
则电影院为真实主题类,而中介则为代理类,在真实主题类售卖电影票的基础上,增强功能收取了一定的手续费。

导包

1.使用了Maven管理项目则引入一下坐标即可。
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
2.未使用maven,则可以通过如下方式导包。

参考链接:在文章的后半部分,有下载和导入的方式

在完成环境配置之后,进行CGLIB动态代理的实现:

1.编写实体类。即被代理类,该类并不需要实现接口。
public class NbCinema {
    public void sell(String type){
        System.out.println("售卖火车票!" + "("+type+")");
    }
}
2.通过cglib动态生成代理类,动态生成的代理类为实体类的子类。

新建工厂类,即CglibProxyFactory,该工厂就是用来获取代理对象的,所以我们应该在该工厂类中定义一个获取代理对象的方法,此时,使用CGLIB进行代理的话,获得的代理类就是目标对象所属类的子类。

使用CGLIB来进行代理流程如下:

  1. 创建Enhancer类对象,该类类似于JDK动态代理中的Proxy类。它就是用来获取代理对象的。
  2. 设置父类的字节码对象。使用CGLIB生成的代理类是属于目标类的子类的,也就是说代理类是要继承自目标类的。
  3. 设置回调函数。
public class CglibProxyFactory<T> implements MethodInterceptor {
    private T obj;

    public CglibProxyFactory(T obj){
        this.obj = obj;
    }

    public T getProxyObject(){
        // 创建Enhancer对象,类似于JDK动态代理的Proxy类,下一步就是设置几个参数
        Enhancer enhancer = new Enhancer();
        // 设置父类的字节码对象,
        enhancer.setSuperclass(obj.getClass());
        // 设置回调函数
        enhancer.setCallback(this);
        // 创建代理对象
        T o = (T) enhancer.create(); // 生成的代理对象,为NbCinema类的子类
        return o;
    }

    /*
        intercept方法参数说明:
            o : 代理对象
            method : 真实对象中的方法的Method实例
            args : 实际参数
            methodProxy :代理对象中的方法的method实例
     */
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("收费500");
        //1.生成的代理对象是实际对象的子类,所以这里调用Super方法,即父类的sell方法。
//        Object invoke = methodProxy.invokeSuper(o, args);
        //2.或者还可以使用被代理对象直接进行调用
        Object invoke = method.invoke(obj, args);
        System.out.println("购票成功!!!");
        return invoke;
    }
}
3. 客户端从中介买票
public class CglibProxyTest {

    public static void main(String[] args) {
        NbCinema nbc = new NbCinema();
        CglibProxyFactory gcp = new CglibProxyFactory<NbCinema>(nbc);
        NbCinema nbc_proxy = (NbCinema) gcp.getProxyObject();
        // 执行sell方法时,会回调函数
        // public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
        // 进行执行
        nbc_proxy.sell("二等座");
    }
}

在这里插入图片描述

CGLIB实现动态代理的完整代码:

package com.csdn.proxy.cglibproxy;

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

import java.lang.reflect.Method;

public class NbCinema {
    public void sell(String type){
        System.out.println("售卖火车票!" + "("+type+")");
    }
}

public class CglibProxyFactory<T> implements MethodInterceptor {
    private T obj;

    public CglibProxyFactory(T obj){
        this.obj = obj;
    }

    public T getProxyObject(){
        // 创建Enhancer对象,类似于JDK动态代理的Proxy类,下一步就是设置几个参数
        Enhancer enhancer = new Enhancer();
        // 设置父类的字节码对象,
        enhancer.setSuperclass(obj.getClass());
        // 设置回调函数
        enhancer.setCallback(this);
        // 创建代理对象
        T o = (T) enhancer.create(); // 生成的代理对象,为NbCinema类的子类
        return o;
    }

    /*
        intercept方法参数说明:
            o : 代理对象
            method : 真实对象中的方法的Method实例
            args : 实际参数
            methodProxy :代理对象中的方法的method实例
     */
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("收费500");
        //1.生成的代理对象是实际对象的子类,所以这里调用Super方法,即父类的sell方法。
//        Object invoke = methodProxy.invokeSuper(o, args);
        //2.或者还可以使用被代理对象直接进行调用
        Object invoke = method.invoke(obj, args);
        System.out.println("购票成功!!!");
        return invoke;
    }
}

public class CglibProxyTest {

    public static void main(String[] args) {
        NbCinema nbc = new NbCinema();
        CglibProxyFactory gcp = new CglibProxyFactory<NbCinema>(nbc);
        NbCinema nbc_proxy = (NbCinema) gcp.getProxyObject();
        // 执行sell方法时,会回调函数
        // public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
        // 进行执行
        nbc_proxy.sell("二等座");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

山风wind

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

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

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

打赏作者

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

抵扣说明:

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

余额充值