字节码编程javassist之生成带有注解的类

写在前面

本文看下如何使用javassist生成带有注解的类。

1:程序

  • 测试类
package com.dahuyou.javassist.huohuo.cc;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// 保留到哪个阶段,SOURCE 仅仅在源代码中保留,编译器不保留该信息。CLASS(默认保留方式),编译器保留,但VM不保留。RUNTIME VM保留,即一直在
// SOURCE作用:给人看,有点类似于注释了,但是是源代码的一部分,比如Override,告诉我们这是重写父类的方法
// CLASS作用:编译器用?咋用???
// RUNTIME作用:程序运行使用,用的最多,比如Deprecated
@Retention(RetentionPolicy.RUNTIME)
// 用在哪里 TYPE 类上 METHOD方法上 FIELD用在字段上
@Target(ElementType.TYPE)
public @interface MyAnnotationOnClazz {
    boolean opened() default false;
    String desc() default "";
    int number();
}
package com.dahuyou.javassist.huohuo.cc;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// 保留到哪个阶段,SOURCE 仅仅在源代码中保留,编译器不保留该信息。CLASS(默认保留方式),编译器保留,但VM不保留。RUNTIME VM保留,即一直在
// SOURCE作用:给人看,有点类似于注释了,但是是源代码的一部分,比如Override,告诉我们这是重写父类的方法
// CLASS作用:编译器用?咋用???
// RUNTIME作用:程序运行使用,用的最多,比如Deprecated
@Retention(RetentionPolicy.RUNTIME)
// 用在哪里 TYPE 类上 METHOD方法上 FIELD用在字段上
@Target(ElementType.METHOD)
public @interface MyAnnotationOnMethod {
    String typeName() default "";
    long payAmount();
}
  • 生成代码类
package com.dahuyou.javassist.huohuo.cc;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.Modifier;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.Bytecode;
import javassist.bytecode.ConstPool;
import javassist.bytecode.MethodInfo;
import javassist.bytecode.annotation.Annotation;
import javassist.bytecode.annotation.BooleanMemberValue;
import javassist.bytecode.annotation.LongMemberValue;
import javassist.bytecode.annotation.StringMemberValue;

public class MyDoItttt extends ClassLoader {
    public static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        // 创建类
        CtClass ctClass = pool.makeClass("com.dahuyou.javassist.huohuo.bb.Helloworld_javassist");
        // 创建方法
//        CtMethod queryAmount = new CtMethod(CtClass.doubleType, "queryAmount", new CtClass[]{pool.get(String.class.getName())}, ctClass);
        CtMethod queryAmount = new CtMethod(CtClass.doubleType, "queryAmount", new CtClass[]{}, ctClass);
//        queryAmount.addLocalVariable();
//        queryAmount.
//        CtMethod queryAmount = new CtMethod(CtClass.voidType, "queryAmount", new CtClass[]{pool.get(String.class.getName())}, ctClass);
        queryAmount.setModifiers(Modifier.PUBLIC);
        // 执行到这里,空方法public double queryAmount(String var1) {}就有了
        ctClass.addMethod(queryAmount);

        MethodInfo methodInfo = queryAmount.getMethodInfo();
        // 获取常量池,注意虽然是通过类信息对象获取的,但常量池是属于类级别的,只不过这里和方法做了关联
        ConstPool constPool = methodInfo.getConstPool();
        // 设置类注解
        AnnotationsAttribute annotationsAttribute = new AnnotationsAttribute(constPool, AnnotationsAttribute.invisibleTag);
        Annotation clazzAnnotation = new Annotation("com/dahuyou/javassist/huohuo/cc/MyAnnotationOnClazz", constPool);
        // 设置类注解的属性们
        /*
        String clazzDesc() default "";
        String alias() default "";
        long timeOut() default 350;

            boolean opened() default false;
    String desc() default "";
    int number();

         */
        clazzAnnotation.addMemberValue("opened", new BooleanMemberValue(true, constPool));
        clazzAnnotation.addMemberValue("desc", new StringMemberValue("api描述啊", constPool));
//        clazzAnnotation.addMemberValue("number", new IntegerMemberValue(455, constPool));
        annotationsAttribute.setAnnotation(clazzAnnotation);
        ctClass.getClassFile().addAttribute(annotationsAttribute); // 画龙点睛,调用类的addAttribute添加注解,没有可不行

        // 添加方法注解
        AnnotationsAttribute methodAttribute = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
        Annotation methodAnnotation = new Annotation("com/dahuyou/javassist/huohuo/cc/MyAnnotationOnMethod", constPool);
        methodAnnotation.addMemberValue("typeName", new StringMemberValue("查询费用111", constPool));
        methodAnnotation.addMemberValue("payAmount", new LongMemberValue(562L, constPool));
        methodAttribute.setAnnotation(methodAnnotation);
        methodInfo.addAttribute(methodAttribute);


        Bytecode bytecode = new Bytecode(constPool);
        bytecode.addGetstatic("java/math/BigDecimal", "TEN", "Ljava/math/BigDecimal;");
        bytecode.addInvokevirtual("java/math/BigDecimal", "doublevalue", "()D");
        bytecode.addReturn(CtClass.doubleType);
        methodInfo.setCodeAttribute(bytecode.toCodeAttribute());

        ctClass.writeFile();

        // 以下代码总是报:Ljava/math/BigDecimal;java.lang.ClassFormatError: Arguments can't fit into locals... 感觉是本地变量表不够大导致。但不知道该如何设置
        System.out.println("-------华丽的分割线-------");
       /* byte[] bytes = ctClass.toBytecode();
        Class<?> clazzNew = new MyDoItttt().defineClass("com.dahuyou.javassist.huohuo.bb.Helloworld_javassist", bytes, 0, bytes.length);
        MyAnnotationOnClazz annotationOnClazz = clazzNew.getAnnotation(MyAnnotationOnClazz.class);
        System.out.println("annotationOnClazz.opened: " + annotationOnClazz.opened());
        System.out.println("annotationOnClazz.desc: " + annotationOnClazz.desc());

        MyAnnotationOnMethod annotationOnMethod = clazzNew.getDeclaredMethod("queryAmount").getAnnotation(MyAnnotationOnMethod.class);

        System.out.println("annotationOnMethod.payAmount: " + annotationOnMethod.payAmount());
        System.out.println("annotationOnMethod.typeName: " + annotationOnMethod.typeName());*/
    }
}

运行后查看生成的字节码:
在这里插入图片描述

写在后面

参考文章列表

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/787904.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JVM原理(二四):JVM虚拟机锁优化

高效并发是从JDK 5升级到JDK 6后一项重要的改进项&#xff0c;HotSpot虛 拟机开发团队在这个版本上花费了大量的资源去实现各种锁优化技术&#xff0c;如适应性自旋( Adaptive Spinning)、锁消除( Lock Elimination)、锁膨胀(Lock Coarsening)、轻量级锁(Lightweight Locking)、…

了解PPO算法(Proximal Policy Optimization)

Proximal Policy Optimization (PPO) 是一种强化学习算法&#xff0c;由 OpenAI 提出&#xff0c;旨在解决传统策略梯度方法中策略更新过大的问题。PPO 通过引入限制策略更新范围的机制&#xff0c;在保证收敛性的同时提高了算法的稳定性和效率。 PPO算法原理 PPO 算法的核心…

LAMP万字详解(概念、构建步骤)

目录 LAMP Apache 起源 主要特点 软件版本 编译安装httpd服务器 编译安装的优点 操作步骤 准备工作 编译 安装 优化执行路径 添加服务 守护进程 配置httpd 查看 Web 站点的访问情况 虚拟主机 类型 部署基于域名的虚拟主机 为虚拟主机提供域名解析&#xff…

ESP32的I2S引脚及支持的音频标准使用说明

ESP32 I2S 接口 ESP32 有 2 个标准 I2S 接口。这 2 个接口可以以主机或从机模式&#xff0c;在全双工或半双工模式下工作&#xff0c;并且可被配置为 8/16/32/48/64-bit 的输入输出通道&#xff0c;支持频率从 10 kHz 到 40 MHz 的 BCK 时钟。当 1 个或 2 个 被配置为主机模式…

db期末复习自用[应试向 附习题]

第一章 数据库系统实现整体数据的结构化&#xff0c;主要特征之一&#xff0c;是db区别于文件系统的本质区别。 数据库系统三个阶段&#xff1a;人工、文件、数据库系统。 数据库管理系统的功能&#xff1a;数据库定义、操纵 、&#xff08;保护、存储、维护&#xff09;、数…

大模型/NLP/算法面试题总结2——transformer流程//多头//clip//对比学习//对比学习损失函数

用语言介绍一下Transformer的整体流程 1. 输入嵌入&#xff08;Input Embedding&#xff09; 输入序列&#xff08;如句子中的单词&#xff09;首先通过嵌入层转化为高维度的向量表示。嵌入层的输出是一个矩阵&#xff0c;每一行对应一个输入单词的嵌入向量。 2. 位置编码&…

020-GeoGebra中级篇-几何对象之点与向量

本文概述了在GeoGebra中如何使用笛卡尔或极坐标系输入点和向量。用户可以通过指令栏输入数字和角度&#xff0c;使用工具或指令创建点和向量。在笛卡尔坐标系中&#xff0c;示例如“P(1,0)”&#xff1b;在极坐标系中&#xff0c;示例如“P(1;0)”或“v(5;90)”。文章还介绍了点…

SpringBoot + MyBatisPlus 实现多租户分库

一、引言 在如今的软件开发中&#xff0c;多租户(Multi-Tenancy)应用已经变得越来越常见。多租户是一种软件架构技术&#xff0c;它允许一个应用程序实例为多个租户提供服务。每个租户都有自己的数据和配置&#xff0c;但应用程序实例是共享的。而在我们的Spring Boot MyBati…

刷代码随想录有感(130):动态规划——编辑距离

题干&#xff1a; 代码&#xff1a; class Solution { public:int minDistance(string word1, string word2) {vector<vector<int>>dp(word1.size() 1, vector<int>(word2.size() 1));for(int i 0; i < word1.size(); i)dp[i][0] i;for(int j 0; j …

使用Mplayer实现MP3功能

核心功能 1. 界面设计 项目首先定义了一个clearscreen函数&#xff0c;用于清空屏幕&#xff0c;为用户界面的更新提供了便利。yemian函数负责显示主菜单界面&#xff0c;提供了包括查看播放列表、播放控制、播放模式选择等在内的9个选项。 2. 文件格式支持 is_supported_f…

数据抓取技术在视频内容监控与快速读取中的应用

引言 在数字化时代&#xff0c;视频内容的快速读取和监控对于内容提供商来说至关重要。思通数科的OPEN-SPIDER抓取技术为这一需求提供了高效的解决方案。 OPEN-SPIDER技术概述 OPEN-SPIDER是思通数科开发的一种先进的数据抓取技术&#xff0c;它能够&#xff1a; - 高效地从各…

Qt 音频编程实战项目

一Qt 音频基础知识 QT multimediaQMediaPlayer 类&#xff1a;媒体播放器&#xff0c;主要用于播放歌曲、网络收音 机等功能。QMediaPlaylist 类&#xff1a;专用于播放媒体内容的列表。 二 音频项目实战程序 //版本5.12.8 .proQT core gui QT multimedia greate…

基于深度学习的电影推荐系统

1 项目介绍 1.1 研究目的和意义 在电子商务日益繁荣的今天&#xff0c;精准预测商品销售数据成为商家提升运营效率、优化库存管理以及制定营销策略的关键。为此&#xff0c;开发了一个基于深度学习的商品销售数据预测系统&#xff0c;该系统利用Python编程语言与Django框架&a…

在RockyLinux上安装Solr8.11(新版本)

在RockyLinux上安装Solr8.11&#xff08;新版本&#xff09; 安装准备安装java环境 安装Solr下载修改配置开放端口验证一下 安装准备 安装java环境 搜索提供可安装的包 yum search java 我们在这里看到有很多&#xff0c;我这里安装的1.8版本。我们这里选择描述为Runtime en…

斯坦福大学博士在GitHub发布的漫画机器学习小抄,竟斩获129k标星

斯坦福大学数据科学博士Chris Albon在GitHub上发布了一份超火的机器学习漫画小抄&#xff0c;发布仅仅一天就斩获GitHub榜首标星暴涨120k&#xff0c;小编有幸获得了一份并把它翻译成中文版本&#xff0c;今天给大家分享出来&#xff01; 轻松的画风配上让人更容易理解的文字讲…

万字总结GBDT原理、核心参数以及调优思路

万字总结GBDT原理、核心参数以及调优思路 在机器学习领域&#xff0c;梯度提升决策树&#xff08;Gradient Boosting Decision Tree, GBDT&#xff09;以其卓越的预测性能和强大的模型解释能力而广受推崇。GBDT通过迭代地构建决策树&#xff0c;每一步都在前一步的残差上进行优…

【力扣高频题】042.接雨水问题

上一篇我们通过采用 双指针 的方法解决了 经典 容器盛水 问题 &#xff0c;本文我们接着来学习一道在面试中极大概率会被考到的经典题目&#xff1a;接雨水 问题 。 42. 接雨水 给定 n 个非负整数&#xff0c;表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子…

【高校科研前沿】中国农业大学姚晓闯老师等人在农林科学Top期刊发表长篇综述:深度学习在农田识别中的应用

文章简介 论文名称&#xff1a;Deep learning in cropland field identification: A review&#xff08;深度学习在农田识别中的应用&#xff1a;综述&#xff09; 第一作者及单位&#xff1a;Fan Xu&#xff08;中国农业大学土地科学与技术学院&#xff09; 通讯作者及单位&…

【电路笔记】-C类放大器

C类放大器 文章目录 C类放大器1、概述2、C类放大介绍3、C类放大器的功能4、C 类放大器的效率5、C类放大器的应用:倍频器6、总结1、概述 尽管存在差异,但我们在之前有关 A 类、B 类和 AB 类放大器的文章中已经看到,这三类放大器是线性或部分线性的,因为它们在放大过程中再现…

【WebGIS平台】传统聚落建筑科普数字化建模平台

基于上述概括出建筑单体的特征部件&#xff0c;本文利用互联网、三维建模和地理信息等技术设计了基于浏览器/服务器&#xff08;B/S&#xff09;的传统聚落建筑科普数字化平台。该平台不仅实现了对传统聚落建筑风貌从基础到复杂的数字化再现&#xff0c;允许用户轻松在线构建从…