JAVA基础——使用cglib实现动态代理

JAVA 代理模式

​ 简而言之,代理是一种通过创建代理对象的方式,从而实现对被代理对象实现功能增强的一种方式,JAVA 中有静态和动态两种代理,动态代理又可以分为基于接口的动态代理(JDK 实现)和基于子类的动态代理(cglib 实现),这里我们讲解基于子类的动态代理

基于子类的动态代理(cglib 实现的动态代理)

​ 使用代理的好处就是在不修改原代码的基础上可以实现对原方法的增强,使用JDK官方的动态代理主要是依靠Proxy类,这种方法实现的动态代理要求被代理类至少实现一个接口,没有实现接口的类是不能被代理的

​ 那么没有实现接口或者不需要实现接口的类,我们怎么对它进行代理呢?

​ 通过引入第三方cglib库,我们可以实现基于子类的动态代理,使用cglib实现的动态代理也有一个约束条件,就是被代理类不能是最终类

​ 使用cglib实现的动态代理核心是Enhancer类,其实实现的过程和JDK实现动态代理的过程极其类似

导入 jar 包

​ 我是用的是maven工程,所以第一步是要导入cglib的 jar 包,当然手动导入也没有问题,pom.xml文件配置如下:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.1_3</version>
</dependency>

编写被代理类

​ 我这里被代理类主要就实现一个卖东西的功能,之后我们会通过代理类对被代理类中的方法进行增强操作:

package com.lmh.cglib;

import com.lmh.proxy.IPorducer;

/**
 * 生产者
 */
public class Producer {
    public void saleProduct(float money) {
        System.out.println("销售产品,拿到钱 " + money);
    }
}

编写代理类(这里也是一个测试类)

​ 这一步是整个过程的关键,代理类的实现要通过Enhancer类,我们需要通过Enhancer类中的create方法创建一个代理对象,具体实现方法如下,作用是给售价打八折,后面我会详细的解释各部分的功能

package com.lmh.cglib;

import com.lmh.proxy.IPorducer;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 模拟一个消费者
 */
public class Client {
    public static void main(String[] args) {
        Producer producer = new Producer();
        Producer enhancerProducer = (Producer) Enhancer.create(producer.getClass(), new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                // 提供增强代码
                Object returnValue = null;
                Float money = (Float) objects[0];
                if ("saleProduct".equals(method.getName())) {
                    returnValue = method.invoke(producer, money * 0.8f);
                }
                return returnValue;
            }
        });
        enhancerProducer.saleProduct(1000f);
    }
}

​ 这里我们可以看到,enhancerProducer就是我们创建的代理对象,这个对象可以执行被代理类中所有的方法,并且我们可以在代理对象中对被代理类的方法进行增强,这里使用了强转,因为create方法的返回值是Object类型的对象

create方法有两个参数,分别是Class typeCallback callback,其中Class type是值被代理类的字节码文件,这是固定的,因为有了被代理类的字节码后,就相当于可以获取被代理类的全部信息;Callback callback是用于提供增强代码的,一般都是写一个接口的实现,通常情况下都是匿名内部类,这里我们一般不适用Callback接口,而是使用它的子接口实现类MethodInterceptor

MethodInterceptor接口需要重写intercept方法,intercept方法中的内容即为对被代理类的增强,该方法有四个参数:Object oMethod methodObject[] objectsMethodProxy methodProxy

Object o参数,是一个代理对象的引用,Method method是当前执行,即被拦截的被代理类方法,Objects[] objects是当前执行方法所用的参数,索引顺序即为方法定义时参数的顺序,MethodProxy methodProxy指的是当前执行的方法的代理对象

​ 通过向上述代码一样编写,我们就可以实现对被代理类功能的增强!

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个使用CGLIB进行动态代理的简单例子: 假设我们有一个接口UserService,其中定义了一个方法getUserById(int id),我们希望对该方法进行拦截,记录方法的执行时间。我们可以使用CGLIB来生成代理类,并通过MethodInterceptor来实现拦截逻辑。 首先,我们需要引入CGLIB的相关依赖: ```xml <!-- CGLIB --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency> ``` 然后,定义一个UserService的实现类UserServiceImpl: ```java public class UserServiceImpl implements UserService { @Override public User getUserById(int id) { // 模拟查询数据库 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return new User(id, "张三"); } } ``` 接下来,我们定义一个MethodInterceptor来实现拦截逻辑: ```java public class TimeInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { long start = System.currentTimeMillis(); Object result = proxy.invokeSuper(obj, args); long end = System.currentTimeMillis(); System.out.println("方法" + method.getName() + "执行时间:" + (end - start) + "ms"); return result; } } ``` 最后,我们使用CGLIB生成代理类,将拦截逻辑加入到代理类中: ```java public class CglibTest { public static void main(String[] args) { UserServiceImpl userService = new UserServiceImpl(); Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(userService.getClass()); enhancer.setCallback(new TimeInterceptor()); UserService proxy = (UserService) enhancer.create(); proxy.getUserById(1); } } ``` 在上面的代码中,我们使用Enhancer类来生成代理类,将原始的UserService实现类作为代理类的父类,然后设置MethodInterceptor作为代理类的回调函数。最后,我们通过enhancer.create()方法来创建代理类,并将其强制转换为UserService接口类型,从而实现代理类的功能。 当我们调用代理类的getUserById方法时,MethodInterceptor中的intercept方法将被执行,从而实现了对方法的拦截。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值