javassist字节码增强技术

一、前言:

简单理解就是在原来方法的前后添加新的代码(扩展之前方法的代码)

这个是springAOP切面的基础

(springAOP切面就是给原有代码前后增加新代码)(为了更方便扩充新功能<只编写下边main中代码>)

<Spring则是只需要编写"切面类" 就可以了>

二、代码:

2.1.导包:
<dependencies>
    <dependency>
        <groupId>org.ow2.asm</groupId>
        <artifactId>asm</artifactId>
        <version>9.1</version>
    </dependency>
    <dependency>
        <groupId>org.javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.28.0-GA</version>
    </dependency>
</dependencies>
2.2.代码:
package com.java.jvm.bytecode.service;

/**
 * 定义一个普通的业务对象,我们现在要通过一定
 * 的技术对这个对象的方法进行功能增强。
 * 例如:
 *  1)在方法体代码执行之前做一些事情
 *  2)在方法体代码执行之后做一些事情
 */
public class ResourceService {

    public  void handle(){
        System.out.println("ResourceService--handle");
    }
}
package com.java.jvm.bytecode;

import com.java.jvm.bytecode.service.ResourceService;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

/*
基于此类为com.java.jvm. bytecode . service. ResourceService做功能增强
思考:
1)对目标类中的方法要进行功能增强的一个基本步骤是怎样的?
1.1)如何获取目标类(基于CtLassPool获取)
1.2)如何获取目标方法(基FctClass获取)
1.3)如何为方法进行功能增强(基FCtMethod实现)
 */
public class JavassistDemo {
    public static void main(String[] args) throws Exception {//被AppClassLoader已经加载了
        ResourceService  rs1=new ResourceService();//加上这一行代码后边的Javassist就会报异常
        //.CannotCompileException: by java.lang.ClassFormatError: loader (instance of
        // sun/misc/Launcher$AppClassLoader):
        // attempted  duplicate class definition for name:
        // "com/java/jvm/bytecode/service/ResourceService"
        //大概意思是AppClassLoader类加载器视图加载已经加载过的一个类, 所以不能实现已经加载过的类,就不能替换
        //某个class已经运行(已经加载), 再次加载进行加强Javassist是行不通的

        //1.获取目标类(目标类的信息会封装到CtClass对象中)//本行代码会加载ResourceService
        CtClass ctclass= ClassPool.getDefault().get(
            "com.java.jvm.bytecode.service.ResourceService");
        //2.获取目标方法信息
        CtMethod targetMethod=ctclass.getDeclaredMethod("handle");
        //3./3.执行方法功能增强
        //注意:{System.out.println("start");} 表示代码块
        //本案例执行一次会增强一次,执行第二次会增强第二次
        targetMethod.insertBefore("{System.out.println(\"start\");}");

        // insertAfter的时候会自动添加一行Object var2=null;(以后待研究)
        targetMethod.insertAfter("{System.out.println(\"end\");}");
        //4.创建新的字节码对象
        Class<?>  aclass= ctclass.toClass();
        ResourceService rs=(ResourceService)aclass.newInstance();

        rs.handle();
        //原本的f_javassist_demo/target/classes/com/java/jvm/bytecode/
        //下的serviceResourceService.class字节码是2022-05-21  16:02生成的        
        //执行了下边的writeFile()生成事件就变成了2022-05-21  16:03
        //将新的字节码对象以class文件的形式存储到磁盘
        ctclass.writeFile("f_javassist_demo/target/classes");
    }

}

2.3.结果分析:
//上边案例执行之后ResourceService生成的字节码反编译之后如下
public void handle(){
    System.out.println("start");
    System.out.println("handle()");
    Object var2=null;
    System.out.println("end");
}

2022-05-21 16:02 ZhaoYQ

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值