首页 > 编程语言 >jdk代理 cglib代理 asm javassist

jdk代理 cglib代理 asm javassist

时间:2023-06-27 18:35:30浏览次数:41  
标签:target Object 代理 class cglib new public asm name

jdk代理实现代码:

public class JdkProxyC implements InvocationHandler {
    private Object target;

    public JdkProxyC(Object target) {
        this.target = target;
    }

    public Object getProxy() throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
        /**
         * ClassLoader loader,
         * Class<?>[] interfaces,
         * InvocationHandler h
         */
        ClassLoader loader = this.target.getClass().getClassLoader();
        Class<?>[] interfaces = this.target.getClass().getInterfaces();
        InvocationHandler handler = this; //实现 InvocationHandler 接口的类

        Object instance = Proxy.newProxyInstance(loader, interfaces, handler);
        return instance;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理前----->");
        Object obj = method.invoke(this.target, args);
        System.out.println("代理后----->");
        return obj;
    }

    public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
        //设置开启代理类.class文件的输出
        System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true");

        UserServer o = (UserServer) new JdkProxyC(new UserServerImpl()).getProxy();//必须转成接口
        o.proxyMethod();
    }
}
View Code
ProxyGenerator.generateProxyClass()接口输出jdk代理类的字节码,里面的 saveGeneratedFiles 开关:
private static final boolean saveGeneratedFiles =
        java.security.AccessController.doPrivileged(
                new GetBooleanAction(
                        "jdk.proxy.ProxyGenerator.saveGeneratedFiles"));

是"jdk.proxy.ProxyGenerator.saveGeneratedFiles“值的由来,默认是false, 在main函数中设置 System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true"); 开启这个开关,就会输出代理类的 .class文件,方便查看代理过程

 

cglib代理实现代码:

public class CglibProxy implements MethodInterceptor, CallbackFilter {

    private Object target;

    public CglibProxy(Object target) {
        this.target = target;
    }

    public Object getProxy() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());//设置类、接口
        enhancer.setCallback(this);// 实现 MethodInterceptor 接口的类

        //设置Callback[] callbacks 数组
        //enhancer.setCallbacks(callbacks);
        //实现 CallbackFilter接口  方法返回CallbackFilter数组下标
        //enhancer.setCallbackFilter(this);

        return enhancer.create();//返回 创建代理类
    }

    /**
     * @param o           增强对象
     * @param method      调用方法
     * @param objects     方法参数
     * @param methodProxy 调用父类方法的代理
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("代理前----->");
        //一下三种方式均可调用方法,通过代理类源码,可以分析其不同
//        method.invoke(this.target, objects);
//        methodProxy.invoke(this.target, objects);//target速度更快
//        methodProxy.invokeSuper(o, objects);//o:代理对象
        System.out.println("代理后----->");
        return null;
    }

    @Override
    public int accept(Method method) {
        return 0;//默认返回0
    }

    public static void main(String[] args) {
        UserServerImpl proxy = (UserServerImpl) new CglibProxy(new UserServerImpl()).getProxy();
        proxy.proxyMethod();
    }
}
View Code

cglib代理类的对应 .class文件的输出需要如下配置,没有“VM选项的”,需要点击“修改选项”选中“添加VM选项”,然后增加  -Dcglib.debugLocation=F:\WorkSpaceJava\spring_ioc_configration\jdk\cglib 等号后边是你想要输出的代理类字节文件的路径

cglib代理类的生成是通过asm进行字节码生成的。 字节码操作的另一项技术是 javassist

asm 需要依赖的包:

<!-- https://mvnrepository.com/artifact/org.ow2.asm/asm -->
<dependency>
    <groupId>org.ow2.asm</groupId>
    <artifactId>asm</artifactId>
    <version>9.5</version>
</dependency>

asm 通过字节码生成Person字节码类示例:

public class TestAsm {
    public static void main(String[] args) throws IOException {
        ClassWriter classWriter = new ClassWriter(0);

        // 通过visit方法确定类的头部信息
        classWriter.visit(Opcodes.V1_8,// java版本
                Opcodes.ACC_PUBLIC,// 类修饰符
                "Person", // 类的全限定名
                null, "java/lang/Object", null);

        //创建构造函数
        MethodVisitor mv = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitCode();
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>","()V",false);
        mv.visitInsn(Opcodes.RETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();

        // 定义test方法
        MethodVisitor methodVisitor = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "test", "()V", null, null);
        methodVisitor.visitCode();
        methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
        methodVisitor.visitLdcInsn("hello world!");
        methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V",false);
        methodVisitor.visitInsn(Opcodes.RETURN);
        methodVisitor.visitMaxs(2, 2);
        methodVisitor.visitEnd();
        classWriter.visitEnd();
        // 使classWriter类已经完成
        // 将classWriter转换成字节数组写到文件里面去
        byte[] data = classWriter.toByteArray();

        File file = new File("F:\\WorkSpaceJava\\spring_ioc_configration\\jdk\\asm\\Person.class");
        FileOutputStream fout = new FileOutputStream(file);
        fout.write(data);
        fout.close();

    }
}
View Code

生成Person字节码类:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

public class Person {
    public Person() {
    }

    public void test() {
        System.out.println("hello world!");
    }
}

 

 javassist需要依赖的包:

<!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.29.2-GA</version>
</dependency>

 javassist通过字节码生成Person字节码类示例:

public class TestJavassist {
    public static void main(String[] args) throws NotFoundException, CannotCompileException, IOException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        ClassPool pool = ClassPool.getDefault();

        // 1. 创建一个空类
        CtClass cc = pool.makeClass("com.test.Person");

        // 2. 新增一个字段 private String name;
        // 字段名为name
        CtField param = new CtField(pool.get("java.lang.String"), "name", cc);
        // 访问级别是 private
        param.setModifiers(Modifier.PRIVATE);
        // 初始值是 "beijing"
        cc.addField(param, CtField.Initializer.constant("beijing"));

        // 3. 生成 getter、setter 方法
        cc.addMethod(CtNewMethod.setter("setName", param));
        cc.addMethod(CtNewMethod.getter("getName", param));

        // 4. 添加无参的构造函数
        CtConstructor cons = new CtConstructor(new CtClass[]{}, cc);
        cons.setBody("{name = \"beijing\";}");
        cc.addConstructor(cons);

        // 5. 添加有参的构造函数
        cons = new CtConstructor(new CtClass[]{pool.get("java.lang.String")}, cc);
        // $0=this / $1,$2,$3... 代表方法参数
        cons.setBody("{$0.name = $1;}");
        cc.addConstructor(cons);

        // 6. 创建一个名为printName方法,无参数,无返回值,输出name值
        CtMethod ctMethod = new CtMethod(CtClass.voidType, "printName", new CtClass[]{}, cc);
        ctMethod.setModifiers(Modifier.PUBLIC);
        ctMethod.setBody("{System.out.println(name);}");
        cc.addMethod(ctMethod);

        //这里会将这个创建的类对象编译为.class文件
        cc.writeFile("F:\\WorkSpaceJava\\spring_ioc_configration\\jdk\\javassist");



        // 这里不写入文件,直接实例化
//        Object person = cc.toClass().newInstance();
//        // 设置值
//        Method setName = person.getClass().getMethod("setName", String.class);
//        setName.invoke(person, "dadududu");
//        // 输出值
//        Method execute = person.getClass().getMethod("printName");
//        execute.invoke(person);

    }

}
View Code

 

生成Person字节码类:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.test;

public class Person {
    private String name = "beijing";

    public void setName(String var1) {
        this.name = var1;
    }

    public String getName() {
        return this.name;
    }

    public Person() {
        this.name = "beijing";
    }

    public Person(String var1) {
        this.name = var1;
    }

    public void printName() {
        System.out.println(this.name);
    }
}

 

标签:target,Object,代理,class,cglib,new,public,asm,name
From: https://www.cnblogs.com/ruber/p/17509584.html

相关文章

  • java动态代理技术
    主要用来做方法的增强,让你可以在不修改源码的情况下,增强一些方法,在方法执行前后做任何你想做的事情(甚至根本不去执行这个方法),因为在InvocationHandler的invoke方法中,你可以直接获取正在调用方法对应的Method对象,具体应用的话,比如可以添加调用日志,做事务控制等。还......
  • 论代理ip池的重要性
      在当今互联网时代,代理IP池成为了许多网络应用和数据采集领域中不可或缺的工具。它的重要性不容忽视。下面就让我们一起来深度的了解一下代理ip为什么重要和它的作用。代理ip池的定义及作用  代理IP池是一种维护大量代理IP地址的系统,用于隐藏真实的IP地址并提供更多的访......
  • LTV-61L-ASEMI代理台湾光宝高速光耦LTV-61L
    编辑:llLTV-61L-ASEMI代理台湾光宝高速光耦LTV-61L型号:LTV-61L品牌:台湾光宝封装:LSOP-6引脚数量:6类型:光耦特性:台湾光宝、IGBT驱动器、储能专用光耦\高速光耦封装尺寸:如图工作温度:-40°C~105°C特性:CMOS输出,负逻辑缓冲器输出宽电源电压:2.7V–5.5V低电源电流IDD:最大1.0mA低正向电流IF:......
  • 代理在爬虫中的应用以及如何测试代理是否成功
    1.查看origin的value值如果和proxies相同,则代理生效: 2.测试代理成功后,将代理添加到爬虫程序中使用: ......
  • 结构型模式-静态代理模式
    #模式类型:结构性模型#模型方法:静态代理模式#作用:在不修改目标代码的情况下,可以控制目标代码的访问,可以在其前后添加自己的业务代码#使用场景:监控。日志,限流fromabcimportABCMeta,abstractmethodclassITeacher(metaclass=ABCMeta):"""教师接口"""@abs......
  • LTV-60L-ASEMI代理台湾光宝储能专用光耦LTV-60L
    编辑:llLTV-60L-ASEMI代理台湾光宝储能专用光耦LTV-60L型号:LTV-60L品牌:台湾光宝封装:LSOP-6工作温度:-40°C~105°CLTV-60L特性:LTV-60L系列由高效AlGaAs发光二极管和高速光学探测器组成。此设计提供光耦的输入侧和输出侧之间具有良好的交流和直流隔离。光学探测器的输出具有集电极开路......
  • 免费代理IP从哪里来,怎么提升代理IP质量
    很多人都喜欢使用免费代理IP,毕竟不用花钱,那么免费代理IP是从哪里来的呢?我们一起来看看。1、免费代理IP网站:有一些网站提供免费的公开代理IP,可以直接从这些网站上获取可用代理IP。2、爬虫程序:使用爬虫程序爬取网上公开的代理IP信息,整理归纳后进行验证,筛选出可用的代理IP。3、自建代......
  • 我们对HTTP代理IP有哪些误解呢
    很多人都知道怎么使用HTTP 代理IP,但很多人对HTTP代理IP存在很多误解,我们一起来看看。1、所有代理IP都能够顺利访问被限制的网站:实际上,很多网站都会采取反爬虫措施,例如IP封锁、请求频率限制、验证码识别等等,这些反爬虫措施可能会让部分代理IP失效。因此,我们需要根据不同的网......
  • IP代理与网络安全:保护隐私的关键技术
    在当今数字化时代,保护个人隐私和网络安全至关重要。本文将重点探讨IP代理技术以及它在网络安全领域中的作用。我们将探索IP代理的工作原理、应用场景,以及它如何帮助用户保护个人隐私和数据安全。同时,我们还将介绍一些与IP代理相关的网络安全措施,以帮助读者加强网络安全意识和保护措......
  • LTV-50L-ASEMI代理台湾光宝高速光耦LTV-50L
    编辑:llLTV-50L-ASEMI代理台湾光宝高速光耦LTV-50L型号:LTV-50L品牌:台湾光宝封装:LSOP-6引脚数量:6类型:光耦特性:台湾光宝、IGBT驱动器、储能专用光耦\高速光耦封装尺寸:如图工作温度:-55°C~100°CLTV-50L描述:LTV-50L高速光电耦合器由高效AlGaAs发光二极管和高速光学探测器组......