Java – 动态创建子类

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

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

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

我想最后得到一个课程:

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

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

我特别喜欢的一个图书馆可以在这里使用; 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,它可以让您找到任何您不确定的东西。

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

使用Javassist很容易:

 import javassist.CannotCompileException; import javassist.ClassPool; import javassist.CtClass; import javassist.NotFoundException; static Class 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依赖:

   org.javassist javassist 3.22.0-GA  

Java代理可能能够满足您的需求 – 它们本质上允许您在对象之上动态分层function,因为您可以拦截对该对象的任何方法调用,并自己处理它们或将方法调用分派给底层类。 根据您要查看的内容,可能会获得与动态创建子类相同的结果

Oracle在他们的网站上有一个不错的介绍 (URL引用Java版本1.4.2,但我不认为这种行为在最近的版本中已经改变)。 这是一个更简洁的示例 ,它为代理代码的外观提供了良好的风格。

也可以使用直接字节代码操作(由ASM框架支持)来做事情,但是我想使用代理将是一种更简单的方法。