CGLib LazyLoader接口

本文将介绍CGLib 的 LazyLoader接口

在 CGLib 中,LazyLoader 接口用来延迟加 Enhancer 回调。并且该接口继承了 Callback 接口,Callback 接口没有定义任何方法(即一个标识接口,类似 JDK 的 java.io.Serializable 接口),Enhancer 使用的所有回调接口都扩展了这个接口。

LazyLoader 接口除了继承 Callback 接口外,自己还定义了一个 loadObject() 方法,它的定义如下:

  • java.lang.Object loadObject() throws java.lang.Exception

    返回原始方法调用应该调度的对象。在调用增强实例中的第一个延迟加载方法时立即调用。然后,将来对代理实例的每次方法调用都使用相同的对象。

示例代码

(1)创建被代理的类,代码如下:

/**
 * 被代理的类
 * @author hxstrive.com 2021/12/29
 */
public class HelloWorld {
    private String msg;

    public HelloWorld(String msg) {
        this.msg = msg;
    }

    public HelloWorld() {
        this("hello world");
    }

    public String test(){
        return this.msg;
    }

}

(2)创建客户端代码,通过 Enhancer 类的 setCallback() 方法设置 LazyLoader 类型回调方法。然后在 LazyLoader 回调的 loadObject() 方法中返回目标实例对象。代码如下:

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.LazyLoader;

/**
 * 验证 setCallback() 设置 LazyLoader 接口
 * @author hxstrive.com 2021/12/31
 */
public class CglibDemo {

    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(HelloWorld.class);
        enhancer.setCallback(new LazyLoader() {
            @Override
            public Object loadObject() throws Exception {
                return new HelloWorld("lazyLoader test");
            }
        });

        HelloWorld sample = (HelloWorld) enhancer.create();
        System.out.println("sample.test():\n" + sample.test());
        System.out.println("\nsample.toString():\n" + sample.toString());
        System.out.println("\nsample.getClass():\n" + sample.getClass());
        System.out.println("\nsample.hashCode():\n" + sample.hashCode());
    }

}

运行结果如下:

sample.test():
lazyLoader test

sample.toString():
com.hxstrive.cglib.callback.demo2.HelloWorld@108c4c35

sample.getClass():
class com.hxstrive.cglib.callback.demo2.HelloWorld$$EnhancerByCGLIB$$b9769574

sample.hashCode():
277630005

根据上面输出结果可知,CGLib 生成的代理对象实际上调用的原始对象来自我们实现的 LazyLoader 回调类中 loadObject() 方法返回的 HelloWorld 对象。

如果我们在 LazyLoader 回调的 loadObject() 方法中返回一个非 HelloWorld.class 类型的实例,会发生什么情况呢?代码如下:

public static void main(String[] args) {
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(HelloWorld.class);
    enhancer.setCallback(new LazyLoader() {
        @Override
        public Object loadObject() throws Exception {
            return Calendar.getInstance();
        }
    });

    HelloWorld sample = (HelloWorld) enhancer.create();
    System.out.println("sample.test():\n" + sample.test());
    System.out.println("\nsample.toString():\n" + sample.toString());
    System.out.println("\nsample.getClass():\n" + sample.getClass());
    System.out.println("\nsample.hashCode():\n" + sample.hashCode());
}

运行上面代码将输出如下错误信息:

Exception in thread "main" java.lang.ClassCastException: java.util.GregorianCalendar cannot be cast to com.hxstrive.cglib.callback.demo2.HelloWorld
at com.hxstrive.cglib.callback.demo2.HelloWorld$$EnhancerByCGLIB$$b9769574.test(<generated>)
at com.hxstrive.cglib.callback.demo2.CglibDemo2.main(CglibDemo2.java:25)
在年轻人的颈项上,没有什么东西能比事业心这颗灿烂的宝珠更迷人的了。 —— 哈菲兹
0 不喜欢
说说我的看法 -
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号