cglib

ASM是一个非常高效的Java字节码操控和分析框架,它允许开发者在运行时或者编译时期动态地生成、改变或者分析类。ASM提供的功能强大且灵活,适用于诸如框架开发、代码优化、代码生成等多种场景

需求:用 asm 编写一个类并运行输出hello word

依赖

<dependency>

    <groupId>org.ow2.asm</groupId>

    <artifactId>asm</artifactId>

    <version>9.1</version>

</dependency>

public static void main(String[] args) throws Exception {

         // 类名,包括包名,这里简化处理,不指定包名
        String className = "com.asm.test.ExampleClass";
        String fullName = className.replace('.', '/'); // 将点换成斜杠,因为ASM内部使用的是内部类名表示法

        // 创建ClassWriter对象,用于生成字节码
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);

        // 定义类,public class ExampleClass
        cw.visit(Opcodes.V1_8, // Java版本号,这里是Java 8
                Opcodes.ACC_PUBLIC, // 类访问修饰符,这里是public
                fullName, // 类名
                null, // 类签名,这里省略
                "java/lang/Object", // 父类,这里是Object
                null); // 实现的接口,这里没有实现任何接口

        // 添加默认构造函数
        MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitVarInsn(Opcodes.ALOAD, 0); // 加载this引用
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); // 调用父类构造函数
        mv.visitInsn(Opcodes.RETURN); // 返回
        mv.visitMaxs(1, 1); // 设置最大栈和局部变量大小,这里简化处理
        mv.visitEnd();

        // 添加sayHello()方法
        mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "sayHello", "()V", null, null);
        mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
        mv.visitLdcInsn("Hello, World!"); // 将字符串常量推入栈顶
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); // 调用println方法
        mv.visitInsn(Opcodes.RETURN);
        mv.visitMaxs(2, 1); // 设置最大栈和局部变量大小
        mv.visitEnd();

        // 结束类定义
        cw.visitEnd();

        // 生成字节码到文件
        byte[] code = cw.toByteArray();
        FileOutputStream fos = new FileOutputStream("target/classes/"+fullName + ".class");
        fos.write(code);
        fos.close();

        System.out.println("Generated class file: " + className + ".class");
        // 加载ExampleClass
        Class<?> exampleClass = Class.forName(className); // 注意这里的类名不需要加.class
        
        // 创建ExampleClass的实例
        Object instance = exampleClass.getDeclaredConstructor().newInstance();
        
        // 获取sayHello方法
        Method sayHelloMethod = exampleClass.getMethod("sayHello");
        
        // 调用sayHello方法
        sayHelloMethod.invoke(instance);

    }

CGlib (Code Generation Library) 是一个强大的高性能的代码生成库,它为Java语言提供了一个非常便利的API来扩展Java类与实现接口。不同于ASM库直接操作字节码,CGlib采取了更高层次的抽象,使得开发者可以以面向对象的方式创建代理类或者子类,而无需了解底层字节码的细节。CGlib主要用于以下几个场景:

  1. 动态代理:当不能使用Java原生的java.lang.reflect.Proxy(仅能代理实现了接口的类)时,CGlib可以创建目标类的子类作为代理,因此适用于没有实现接口的类的增强。

  2. AOP(面向切面编程):在AOP框架中,如Spring AOP,默认情况下使用JDK动态代理,但若目标对象没有实现接口,则转而使用CGlib来创建代理对象,实现在方法前后插入自定义逻辑(如日志记录、事务管理等)。

  3. 持久化框架:一些ORM(对象关系映射)框架,如Hibernate的动态代理功能,可能会用到CGlib来实现延迟加载等特性。

  4. 其他框架与库:许多Java应用框架,如Spring、MyBatis等,都可能间接使用CGlib来增强或代理对象。

使用cglib创建代理

依赖

    <dependency>

        <groupId>cglib</groupId>

        <artifactId>cglib</artifactId>

        <version>3.3.0</version>

    </dependency>


public class CGlibProxyExample implements MethodInterceptor {

    public Object getProxy(Class clazz) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        // enhancer.setInterfaces(new Class[]{SomeInterface.class});
        // 设置回调方法
        enhancer.setCallback(this);
        // 创建并返回代理对象
        return enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before method execution");
        Object result = proxy.invokeSuper(obj, args); // 调用原始方法
        System.out.println("After method execution");
        return result;
    }

    public static void main(String[] args) {
        CGlibProxyExample example = new CGlibProxyExample();
        SomeService proxy = (SomeService) example.getProxy(SomeService.class);
        proxy.doSomething();
        // ((SomeInterface)proxy).doOtherSomething();
    }
}

public class SomeService {
    public void doSomething() {
        System.out.println("do something exe");
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值