I'd like to create a subclass programatically. I guess I have few options - Javassist, CGLib, BCEL, or ASM.
The use case is that one app's internals are class-oriented, and extensions are class-based. Therefore I can't have a single class as a base for multiple extensions driven by externalized scripts.
Now - how would I do that? I've found examples with intercepting method calls, field access, initialization etc. But nothing about subclassing.
I'd like to end up with a class which:
super(...)
)I know it's possible because various dynamic languages integrations, like GroovyClassLoader
, can do that.
It's quite easy with 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 dependency:
<!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.22.0-GA</version>
</dependency>