Java - 动态创建子类

Ond*_*žka 10 java subclass cglib

我想以编程方式创建一个子类.我想我有几个选择 - Javassist,CGLib,BCEL或ASM.

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

现在 - 我该怎么做?我找到了拦截​​方法调用,字段访问,初始化等的例子.但是没有关于子类化的内容.

我想最后得到一个课程:

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

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

Con*_*ies 7

我特别喜欢的一个图书馆可以在这里使用; 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();
Run Code Online (Sandbox Code Playgroud)

它非常灵活,绝对值得一试,如果你想保留你的头发,我个人发现javassist的大量使用有时会变得非常丑陋和混乱,bytebuddy感觉就像一个需要呼吸的新鲜空气!

Rafael Winterhalter也积极参与StackOverflow,这可以让你找到任何你不确定的东西.

编辑:我对尸检的道歉.当朋友将问题链接到忘记检查日期时,登陆这里.


Ond*_*žka 6

使用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();
}
Run Code Online (Sandbox Code Playgroud)

Maven依赖:

<!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.22.0-GA</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)