Java代理模式——CGLIB动态代理

对于动态代理,如果没有定义代理类接口,而只是定义了代理类,那么此时JDK动态代理就无法使用了,因为JDK动态代理要求必须定义接口,它是对接口进行代理的,现在没有定义接口,那么自然就不能使用JDK动态代理了。

这时,我们就可以使用CGLIB动态代理来实现。

CGLIB是一个功能强大,高性能的代码生成包(CGLIB就是用来生成代码的,它也是在内存中动态的去生成的)

因为CGLIB是第三方提供的包,所以我们需要在maven工程中引入对应jar包:

        <!--CGLIB-->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.3.0</version>
        </dependency>

接下来,CGLIB动态代理代码实现:

新建被代理类,我们这里用NaiKeCloth(耐克服装厂)举例。此时并不需要再新建Cloth接口,因为我们现在是要使用CGLIB进行代理

package com.hxk.pattern.proxy.cglib_proxy.lx;

/**
 * 被代理类:耐克服装厂
 *
 * @author ***
 * @create 2022-05-20 20:17
 */
public class NaiKeCloth {
    public void makeCloth(String type){
        System.out.println("制作服装:" + type);
    }

    public String brand(){
        return "我的品牌是:耐克";
    }
}

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

使用CGLIB来进行代理:

  1. 创建Enhancer类对象,该类类似于JDK动态代理中的Proxy类。它就是用来获取代理对象的。注意该类是属于CGLIB里面的,所以我们要导入相对应的包。
  2. 设置父类的字节码对象。使用CGLIB生成的代理类是属于目标类的子类的,也就是说代理类是要继承自目标类的。
  3. 设置回调函数。

ProxyFactory代码实现:

package com.hxk.pattern.proxy.cglib_proxy.lx;

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

import java.lang.reflect.Method;

/**
 * @author ***
 * @create 2022-05-20 20:19
 */
public class ProxyFactory<T> implements MethodInterceptor {

    private T obj;

    public ProxyFactory(T obj) {
        this.obj = obj;
    }
    public T getProxy(){
        // 1. 创建Enhancer类对象,它类似于咱们JDK动态代理中的Proxy类,该类就是用来获取代理对象的
        Enhancer enhancer = new Enhancer();
        // 2. 设置父类的字节码对象。为啥子要这样做呢?因为使用CGLIB生成的代理类是属于目标类的子类的,也就是说代理类是要继承自目标类的
        enhancer.setSuperclass(obj.getClass());
        // 3. 设置回调函数
        enhancer.setCallback(this);
        // 4. 创建代理对象
        return (T) enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        if (method.getName().equals("makeCloth")){
            System.out.println("制作服装前的准备.........");
        }
        Object invoke = method.invoke(obj, objects);
        if (method.getName().equals("makeCloth")){
            System.out.println("对制作好的服装打包处理");
        }
        return invoke;
    }
}

最后就是测试类进行测试:

package com.hxk.pattern.proxy.cglib_proxy.lx;

/**
 * @author ***
 * @create 2022-05-21 8:36
 */
public class Client {
    public static void main(String[] args) {
        NaiKeCloth cloth = new NaiKeCloth();
        NaiKeCloth proxy = new ProxyFactory<NaiKeCloth>(cloth).getProxy();
        proxy.makeCloth("短袖");
        String brand = proxy.brand();
        System.out.println(brand);
    }
}

我们来看一下运行结果:

 

最后,若是有接口,则你可以使用JDK动态代理(看我主页静态代理和动态代理)带来实现代理;若是没有接口,则你就可以使用CGLIB进行代理。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

hxung

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

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

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

打赏作者

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

抵扣说明:

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

余额充值