Javassist:创建一个用泛型扩展另一个接口的接口

Javassist:创建一个用泛型扩展另一个接口的接口,java,javassist,Java,Javassist,我正在项目中使用,需要在运行时创建以下接口: package com.example; import org.springframework.data.repository.CrudRepository; import com.example.Cat; public interface CatRepository extends CrudRepository<Cat, Long> {} package.com.example; 导入org.springframework.dat

我正在项目中使用,需要在运行时创建以下接口:

package com.example;

import org.springframework.data.repository.CrudRepository;
import com.example.Cat;

public interface CatRepository extends CrudRepository<Cat, Long> {}
package.com.example;
导入org.springframework.data.repository.crudepository;
导入com.example.Cat;
公共接口CatRepository扩展了Crudepository{}
虽然我在创建接口
CatRepository
扩展
crudepository
时没有遇到问题,但我不明白(从文档和查看源代码)如何将
com.example.Cat
java.lang.Long
指定为超级接口的泛型类型

请注意:

  • com.example.Cat
    :使用javassist在运行时创建(没有问题,我也测试过,它可以正常工作)
  • org.springframework.data.repository.crudepository
    :库中存在的类
如果有人能帮上忙,那就太好了

谢谢!卢卡

简短回答 可以在Javassist中使用

长答案(带代码) 您可能已经拥有的代码如下所示:

 ClassPool defaultClassPool = ClassPool.getDefault();
 CtClass superInterface = defaultClassPool.getCtClass(CrudRepository.class
            .getName());
 CtClass catRepositoryInterface = defaultClassPool.makeInterface("CatRepository", ctClass);

// something is missing here :-(

 catRepositoryInterface.toClass()
但是,正如您已经说过的,这不会添加有关泛型的信息。为了获得编译源代码时获得的相同字节码,您需要在注释所在的位置执行以下操作:

SignatureAttribute signatureAttribute = new SignatureAttribute(
            classFile.getConstPool(),
     "Ljava/lang/Object;Lorg/springframework/data/repository/CrudRepository<Lorg/example/Cat;Ljava/lang/Long;>;");
ClassFile metaInformation = catRepositoryInterface.getClassFile();
classFile.addAttribute(signatureAttribute);
SignatureAttribute SignatureAttribute=新的SignatureAttribute(
classFile.getConstPool(),
“Ljava/lang/Object;Lorg/springframework/data/repository/crudepository;”;
ClassFile metaInformation=catRepositoryInterface.getClassFile();
addAttribute(signatureAttribute);
让我们对签名字符串进行分解,以了解其中发生的情况:

  • 你会看到几个L[TYPE],它是什么?L是字节码中定义对象类的标准符号,如果你对

  • “;”被用作多个定义之间的分隔符。让我们看看其中的每一个:

    • Ljava/lang/Object
    • Lorg/springframework/data/repository/Crudepository
第一个定义必须存在,因为在Java语言中,一切都从Java.lang.Object扩展而来(不管是类还是接口)

但最有趣的是第二个,这里有你的类型,有完整的类名和泛型类型定义,所有的都使用L符号。这就是你缺少的:-)


注意

请记住,如果要从多个接口扩展,只需将它们添加到列表中即可。例如,以下签名将使接口不仅从CrudePository扩展,而且从Serializable扩展:

Ljava/lang/object;Lorg/springframework/data/repository/CrudRepository<Lorg/example/Cat;Ljava/lang/Long;>;**Ljava/io/Serializable;**
Ljava/lang/object;Lorg/springframework/data/repository/Crudepository**Ljava/io/Serializable**

回答得很好。成功了!谢谢你的完美描述!我会仔细研究,以进一步了解我在做什么。我知道这是一个古老的答案,但你能修复你的三个代码示例吗?什么是
ctClass
,什么是
classFile
,为什么
metaInformation
从未被使用,为什么“**”有意义?