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

JAVA 代理模式

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

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

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

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

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

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

导入 jar 包

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

1
2
3
4
5
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.1_3</version>
</dependency>

编写被代理类

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

1
2
3
4
5
6
7
8
9
10
11
12
package com.lmh.cglib;

import com.lmh.proxy.IPorducer;

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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指的是当前执行的方法的代理对象

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

-------------本文结束感谢您的阅读-------------