栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

字节码技术 Javassist的学习使用(动态加载接口实现类,AOP原理)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

字节码技术 Javassist的学习使用(动态加载接口实现类,AOP原理)

文章目录
    • 官网
    • github
    • 作用
    • 简单使用案例
      • 依赖
      • 动态生成接口的实现
      • 对方法作代理增强

官网

https://www.javassist.org/

github

https://github.com/jboss-javassist/javassist

作用

简单来说Javassist主要用于操作Java字节码,让我们操作字节码变得简单,可以在JVM加载类文件的时候去修改它。与其他字节码编辑器不同的是Javassist提供了两个级别的API,源代码级和字节码级。如果用户使用源级 API,他们可以在不了解 Java 字节码规范的情况下编辑类文件。
目前自己应用到的场景有如下:

  1. 动态加载实现接口的实现类
  2. 动态增强原有类的方法
简单使用案例 依赖
			
            org.javassist
            javassist
            3.22.0-GA
        	
动态生成接口的实现

首先定义一个接口

public interface IHello {
    void sayHello(String name, Integer age);
}

动态生成接口实现类并调用

public class Proxy {

    
    private Class t;

    public Proxy(Class t){
        this.t = t;
    }


    
    private static final String PROXYFREFIX = "$Proxy";
    
    private static final String PROXYSUFFIX = "Impl";


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

        ClassPool pool = ClassPool.getDefault();
        //接口实现类的名字
        Proxy proxy = new Proxy<>(IHello.class);
        String clazzName = proxy.getPackageName() + proxy.getProxyObjectName();
        System.out.println("clazzName: " + clazzName);

        // 创建实现类 = public class com.test.cider.javassist$ProxyIHelloImpl {}
        CtClass targetClass = pool.makeClass(clazzName);

        //获得接口的CtClass  IHello.class.getName() = proxy.t.getClass().getName()
        CtClass interf = pool.getCtClass(IHello.class.getName());
        CtClass[] interfs = new CtClass[]{interf};
        // 这行代码等 = public class ProxyIHelloImpl implements IHello{}
        targetClass.setInterfaces(interfs);
        // 获取接口 sayHello 方法
        CtMethod method = interf.getDeclaredMethod("sayHello");
        // 创建方法
        CtMethod m = new CtMethod(method.getReturnType(),method.getName(),method.getParameterTypes(),targetClass);
        //设置方法的实现类
//        System.out.println("姓名: " + $1 + " 年龄: " + $2);
        m.setBody("        System.out.println("姓名: " + $1 + " 年龄: " + $2);n");
        targetClass.addMethod(m);
        //生成Class文件
//        targetClass.writeFile("C:\Users\java\src\main\resources");
        //生成Class载入内存
        Class target = targetClass.toClass();
        //实例化
        IHello o = (IHello) target.getDeclaredConstructor().newInstance();
        o.sayHello("weihubeats", 18);
    }

    //获取包名
    public String getPackageName(){
        Package aPackage = t.getPackage();
        return aPackage.getName();
    }

    //获取代理对象的名称
    public String getProxyObjectName(){
        return PROXYFREFIX+t.getSimpleName()+PROXYSUFFIX;
    }


}

实际效果

对方法作代理增强

首先写一个需要增强的方法

public class JavassistTest {

    public  String sayHello(String a) {
        System.out.println("原来方法也执行了,参数: " + a);
        return "1223";
    }
}

然后对原有方法进行增强

public class Test {
    public static void  sayHello(String aa) {
        System.out.println("增强" + aa);

    }
    public static void main(String[] args) throws Exception{
        CtClass cc;
        ClassPool pool = ClassPool.getDefault();
        cc = pool.get("com.test.cider.javassist.JavassistTest");
        CtMethod ctMethod = cc.getDeclaredMethod("sayHello");
        ctMethod.insertBefore("com.test.cider.javassist.Test.sayHello($1);");
        cc.toClass();
        JavassistTest javassistTest = new JavassistTest();
        javassistTest.sayHello("haha");
    }

}

执行结果

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/346107.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号