java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Cglib代理

Java的动态代理模式之Cglib代理详解

作者:四叶草

这篇文章主要介绍了Java的动态代理模式之Cglib代理详解,Cglib代理也叫作 子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能扩展, 有些书也将Cglib代理归属到动态代理,需要的朋友可以参考下

1.Cglib 代理模式的基本介绍

  1. 静态代理和 JDK 代理模式都要求目标对象是实现一个接口,但是有时候目标对象只是一个 单独的对象,并没 有实现任何的接口,这个时候可使用目标对象子类来实现代理-这就是 Cglib 代理
  2. Cglib代理也叫作 子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能扩展, 有些书也将Cglib代理归属到动态代理。
  3. Cglib 是一个强大的高性能的代码生成包,它可以在运行期扩展 java 类与实现 java 接口.它广泛的被许多 AOP 的框架使用,例如 SpringAOP,实现方法拦截
  4. 在 AOP 编程中如何选择代理模式:

目标对象需要实现接口,用 JDK 代理

目标对象不需要实现接口,用 Cglib 代理

Cglib 包的底层是通过使用字节码处理框架 ASM 来转换字节码并生成新的类

2.Cglib 代理模式实现步骤

需要引入 cglib 的 jar 文件

/*
cglib包结构:
net.sf.cglib.core    	底层字节码处理类。
net.sf.cglib.transform  该包中的类用于class文件运行时转换或编译时转换。
net.sf.cglib.proxy    	该包中的类用于创建代理和方法拦截。
net.sf.cglib.reflect    该包中的类用于快速反射,并提供了C#风格的委托。
net.sf.cglib.util    	集合排序工具类。
net.sf.cglib.beans    	JavaBean工具类。
*/

在内存中动态构建子类,注意代理的类不能为 final,否则报错java.lang.IllegalArgumentException:

目标对象的方法如果为 final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.

3.cglib动态代理相关的基础类

net.sf.cglib.proxy.Enhancer 主要的增强类。

net.sf.cglib.proxy.MethodInterceptor 主要的方法拦截类,它是Callback接口的子接口,需要用户实现。

net.sf.cglib.proxy.MethodProxy JDK的java.lang.reflect.Method类的代理类,可以方便的实现对源对象方法的调用。

cglib是通过动态的生成一个子类去覆盖所要代理类的非final方法,并设置好callback,则原有类的每个方法调用就会转变成调用用户定义的拦截方法(intercept)

4.Cglib 代理模式应用实例

4.1 导入pom.xml依赖

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.1</version>
</dependency>

4.2 目标类

//火车站
public class TrainStation {

    public void sell() {
        System.out.println("火车站卖票");
    }
}

4.3 代理工厂

//代理工厂
public class ProxyFactory implements MethodInterceptor {

    //声明目标对象
    private TrainStation target = new TrainStation();

    public TrainStation getProxyObject() {
        //创建Enhancer对象,类似于JDK动态代理的Proxy类,下一步就是设置几个参数
        Enhancer enhancer =new Enhancer();

        //设置代理对象的父类的字节码对象(Class类型的对象) , 指定代理对象的父类
        enhancer.setSuperclass(target.getClass());

        //设置回调函数 , 实现调用代理对象的方法时最终都会执行MethodInterceptor的子实现类的intercept方法 , 在这个函数中利用反射完成任意目标类方法的调用
        enhancer.setCallback(this);

        //设置完参数后就可以 ,默认返回的是Object类型 , 可以进行强转 , 创建真正的代理对象
        TrainStation obj = (TrainStation) enhancer.create();
        return obj;
    }
    // intercept方法参数说明:
    //		返回值类型是调用方法的返回值类型
	//		o : 代理对象
	//		method : 真实对象中的方法的Method实例对象
	//		args : 实际参数 , 可以是0到N个
	//		methodProxy :代理对象中的方法的method实例

    public TrainStation intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("代理点收取一些服务费用(CGLIB动态代理方式)");
        //调用目标对象的方法
        TrainStation result = (TrainStation) methodProxy.invokeSuper(o, args);
        return result;
    }
}

Enhancer类的常用方法

方法名功能
public Enhancer() , 无参构造创建Enhancer对象,类似于JDK动态代理的Proxy类,并不是真正的代理对象 , 还没有设置参数
setSuperclass()设置代理对象的父类的字节码对象(Class类型的对象) , 指定代理对象的父类 , 参数一般写目标类的Class对象
setCallback()设置执行哪个对象的回调函数 , 调用代理对象的方法时最终都会执行MethodInterceptor接口的子实现类对象的intercept方法 , 在intercept方法中利用反射完成任意目标类方法的调用 一般让代理工厂实现MethodInterceptor接口 , 那么方法参数就可以写this,这时MethodInterceptor接口的子实现类对象就是代理工厂对象
public Object create()创建真正的代理对象 , 默认返回的是Object类型 , 可以强转为目标对象类型 , 创建真正的代理对象

4.4 测试类

//测试类
public class Client {
    public static void main(String[] args) {
        //创建代理工厂对象
        ProxyFactory factory = new ProxyFactory();
        
        //获取代理对象
        TrainStation proxyObject = factory.getProxyObject();

        proxyObject.sell();
    }
}

5 jdk代理和CGLIB代理

6 代理模式优缺点及使用场景

优点:

缺点:

使用场景:

到此这篇关于Java的动态代理模式之Cglib代理详解的文章就介绍到这了,更多相关Cglib代理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文