除了 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 {@Overridepublic 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();}@Overridepublic 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.CglibCalculatorImplclass 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 不仅可以代理接口还可以代理类,下面试试代理类。- 创建新的目标对象```javapublic 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.CglibCalculatorClassclass com.example.java.proxy.cglib1.CglibCalculatorClass$$EnhancerByCGLIB$$e68ff36c方法调用前,可以添加其他功能....方法调用后,可以添加其他功能....相加结果:3
