簡體   English   中英

Java - 動態創建子類

[英]Java - creating a subclass dynamically

我想以編程方式創建一個子類。 我想我幾乎沒有選擇 - 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();
}

Maven 依賴:

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

這里可以使用我特別喜歡的一個庫; 字節好友

直接取自登陸頁面的示例:

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 上也很活躍,這使得找出任何你不確定的事情變得輕而易舉。

編輯:我為屍檢道歉。 當朋友鏈接問題並忘記檢查日期時登陸這里。

Java 代理可能能夠滿足您的要求——它們本質上允許您在對象之上動態分層功能,因為您可以攔截對該對象的任何方法調用,然后自己處理它們或將方法調用分派給底層類. 根據您要做什么,您可能會獲得與動態創建子類相同的結果

Oracle 在他們的網站上有一個不錯的介紹(URL 引用了 Java 1.4.2 版,但我認為它的行為在最近的版本中沒有改變)。 這是一個更簡潔的示例,它為代理代碼的外觀提供了很好的風格。

也可以使用直接字節碼操作(由ASM 框架支持)來做事,但我認為使用代理將是一種更簡單的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM