除了 jdk 能实现动态的创建代理对象以外,还有一个非常有名的第三方框架:cglib,它也可以做到运行时在内存中动态生成一个子类对象从而实现对目标对象功能的扩展。
cglib 特点如下:
- cglib 不仅可以代理接口还可以代理类,而 JDK 的动态代理只能代理接口
- cglib 是一个强大的高性能的代码生成包,它广泛的被许多 AOP 的框架使用,例如熟知的 Spring AOP,cglib 为他们提供方法的
interception
(拦截)。 - cglib 包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类,速度非常快。
在使用 cglib 之前,需要添加依赖包,如果已经有spring-core的jar包,则无需引入,因为spring中包含了cglib。
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.5</version>
</dependency>
下面还是以两数相加为例,介绍具体的玩法!
创建接口
public interface CglibCalculator {
/**
* 计算两个数之和
* @param num1
* @param num2
* @return
*/
Integer add(Integer num1, Integer num2);
}
目标对象
public class CglibCalculatorImpl implements CglibCalculator {
@Override
public Integer add(Integer num1, Integer num2) {
Integer result = num1 + num2;
return result;
}
}
动态代理对象
public class CglibProxyFactory implements MethodInterceptor {
/**
* 维护一个目标对象
*/
private Object target;
public CglibProxyFactory(Object target) {
this.target = target;
}
/**
* 为目标对象生成代理对象
* @return
*/
public Object getProxyInstance() {
//工具类
Enhancer en = new Enhancer();
//设置父类
en.setSuperclass(target.getClass());
//设置回调函数
en.setCallback(this);
//创建子类对象代理
return en.create();
}
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("方法调用前,可以添加其他功能....");
// 执行目标对象方法
Object returnValue = method.invoke(target, args);
System.out.println("方法调用后,可以添加其他功能....");
return returnValue;
}
}
测试类
public class TestCglibProxy {
public static void main(String[] args) {
//目标对象
CglibCalculator target = new CglibCalculatorImpl();
System.out.println(target.getClass());
//代理对象
CglibCalculator proxyClassObj = (CglibCalculator) new CglibProxyFactory(target).getProxyInstance();
System.out.println(proxyClassObj.getClass());
//执行代理方法
Integer result = proxyClassObj.add(1,2);
System.out.println("相加结果:" + result);
}
}
输出结果
class com.example.java.proxy.cglib1.CglibCalculatorImpl
class com.example.java.proxy.cglib1.CglibCalculatorImpl$$EnhancerByCGLIB$$3ceadfe4
方法调用前,可以添加其他功能....
方法调用后,可以添加其他功能....
相加结果:3
将 cglib 生成的代理类改写为静态实现类大概长这样: ```java public class CglibCalculatorImplByCGLIB extends CglibCalculatorImpl implements Factory {
private static final MethodInterceptor methodInterceptor;
private static final Method method;
public final Integer add(Integer var1, Integer var2) {
return methodInterceptor.intercept(this, method, new Object[]{var1, var2}, methodProxy);
}
//....
}
其中,拦截思路与 JDK 类似,都是通过一个接口方法进行拦截处理!<br />在上文中咱们还介绍到了,cglib 不仅可以代理接口还可以代理类,下面试试代理类。
- 创建新的目标对象
```java
public class CglibCalculatorClass {
/**
* 计算两个数之和
* @param num1
* @param num2
* @return
*/
public Integer add(Integer num1, Integer num2) {
Integer result = num1 + num2;
return result;
}
}
测试类
public class TestCglibProxyClass {
public static void main(String[] args) {
//目标对象
CglibCalculatorClass target = new CglibCalculatorClass();
System.out.println(target.getClass());
//代理对象
CglibCalculatorClass proxyClassObj = (CglibCalculatorClass) new CglibProxyFactory(target).getProxyInstance();
System.out.println(proxyClassObj.getClass());
//执行代理方法
Integer result = proxyClassObj.add(1,2);
System.out.println("相加结果:" + result);
}
}
输出结果
class com.example.java.proxy.cglib1.CglibCalculatorClass
class com.example.java.proxy.cglib1.CglibCalculatorClass$$EnhancerByCGLIB$$e68ff36c
方法调用前,可以添加其他功能....
方法调用后,可以添加其他功能....
相加结果:3