Java-动态创建子类

问题描述 投票:10回答:3

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

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

现在-我该怎么做?我已经找到了拦截​​方法调用,字段访问,初始化等示例。但是关于子类化却一无所获。

我想结束一个上课的人:

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

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

java subclass cglib
3个回答
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();

这是非常灵活的,绝对值得一试,如果您想保持头发,我个人发现大量使用Javassist有时会变得非常丑陋和混乱,bytebuddy感觉就像是急需的新鲜空气!

[Rafael Winterhalter在StackOverflow上也处于活动状态,这使得找出不确定的内容变得容易。

编辑:我为坏死发表歉意。当朋友链接问题并忘记检查日期时,就降落在这里。


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();
}

Maven依赖项:

<!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.22.0-GA</version>
</dependency>

3
投票

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

Oracle在其网站上有一个decent introduction(URL引用Java版本1.4.2,但我认为在更新的版本中其行为没有改变)。这是more concise example,可很好地呈现代理代码的外观。

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

© www.soinside.com 2019 - 2024. All rights reserved.