Java-动态创建子类

Java-动态创建子类,java,subclass,cglib,Java,Subclass,Cglib,我想通过编程创建一个子类。 我想我几乎没有选择——Javassist、CGLib、BCEL或ASM 用例是一个应用程序的内部是面向类的,扩展是基于类的。因此,我不能将一个类作为由外部化脚本驱动的多个扩展的基础 现在-我该怎么做?我发现了一些拦截方法调用、字段访问、初始化等的例子,但没有关于子类化的 我想以一门课结束,这门课: 有一个我想要的名字 是给定类的(直接,最多)子类 从父类复制构造函数(或调用super(…)) 最后,我想给它一些注释 我知道这是可能的,因为各种动态语言集成(如Gro

我想通过编程创建一个子类。 我想我几乎没有选择——Javassist、CGLib、BCEL或ASM

用例是一个应用程序的内部是面向类的,扩展是基于类的。因此,我不能将一个类作为由外部化脚本驱动的多个扩展的基础

现在-我该怎么做?我发现了一些拦截方法调用、字段访问、初始化等的例子,但没有关于子类化的

我想以一门课结束,这门课:

  • 有一个我想要的名字
  • 是给定类的(直接,最多)子类
  • 从父类复制构造函数(或调用
    super(…)
  • 最后,我想给它一些注释

我知道这是可能的,因为各种动态语言集成(如
GroovyClassLoader
)都可以做到这一点。

使用Javassist非常简单:

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;

static Class<? extends DefinitionBasedMigrator> createClass( String fullName )
        throws NotFoundException, CannotCompileException
{
    ClassPool pool = ClassPool.getDefault();

    // Create the class.
    CtClass subClass = pool.makeClass( fullName );
    final CtClass superClass = pool.get( DefinitionBasedMigrator.class.getName() );
    subClass.setSuperclass( superClass );
    subClass.setModifiers( Modifier.PUBLIC );

    // Add a constructor which will call super( ... );
    CtClass[] params = new CtClass[]{
        pool.get( MigratorDefinition.class.getName() ),
        pool.get( GlobalConfiguration.class.getName()) 
    };
    final CtConstructor ctor = CtNewConstructor.make( params, null, CtNewConstructor.PASS_PARAMS, null, null, subClass );
    subClass.addConstructor( ctor );

    return subClass.toClass();
}
import javassist.CannotCompileException;
导入javassist.ClassPool;
导入javassist.CtClass;
导入javassist.NotFoundException;

静态类Java代理可以满足您的要求-它们本质上允许您在对象的顶部动态分层功能,因为您可以拦截对该对象的任何方法调用,并自己处理它们或将方法调用分派给基础类。根据您希望执行的操作,您可以通过动态创建一个子类来获得相同的结果

Oracle在其网站上有一个URL(URL引用Java版本1.4.2,但我认为在更新的版本中这种行为没有改变)。下面是一个示例,它为代理代码的外观提供了一种很好的风格


也可以使用直接字节码操作(由支持)进行操作,但是我认为使用代理将是一种更简单的方法。

这里可以使用一个我特别喜欢的库

直接从登录页获取的示例:

Class<?> dynamicType = new ByteBuddy()
  .subclass(Object.class)
  .method(ElementMatchers.named("toString"))
  .intercept(FixedValue.value("Hello World!"))
  .make()
  .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
  .getLoaded();
classdynamictype=newbytebuddy()
.subclass(Object.class)
.method(ElementMatchers.named(“toString”))
.intercept(FixedValue.value(“helloworld!”)
.make()
.load(getClass().getClassLoader(),ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
它非常灵活,如果你想留着头发的话,绝对值得一看。我个人发现大量使用javassist有时会变得非常难看和凌乱,bytebuddy感觉就像是一口急需的新鲜空气

在StackOverflow上也很活跃,这使得你很容易找到任何你不确定的东西


编辑:我为我的发帖道歉。当一位朋友将问题链接到这里时,我忘了检查日期。

实际上,我先查看了代理,但由于复杂性,我离开了。Javassist非常简单。而且,代理需要一个接口,不能作为普通类被进一步重写。。。无论如何,+1 Bytebuddy链接似乎链接到同一个页面
Class<?> dynamicType = new ByteBuddy()
  .subclass(Object.class)
  .method(ElementMatchers.named("toString"))
  .intercept(FixedValue.value("Hello World!"))
  .make()
  .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
  .getLoaded();