Skip to content

Instantly share code, notes, and snippets.

@aoriani
Last active December 25, 2023 02:16
Show Gist options
  • Save aoriani/43f2cae97648258a5551985fa5386fb1 to your computer and use it in GitHub Desktop.
Save aoriani/43f2cae97648258a5551985fa5386fb1 to your computer and use it in GitHub Desktop.
Shows how to dynamically implement a class Person using ByteBudy
package org.example
import net.bytebuddy.ByteBuddy
import net.bytebuddy.description.modifier.Visibility
import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy
import net.bytebuddy.implementation.FieldAccessor
import net.bytebuddy.implementation.MethodCall
import net.bytebuddy.implementation.MethodDelegation
import net.bytebuddy.implementation.bind.annotation.FieldValue
import net.bytebuddy.matcher.ElementMatchers
val personClass = ByteBuddy()
.subclass(Any::class.java, ConstructorStrategy.Default.NO_CONSTRUCTORS)
.name("Person")
.defineField("firstName", String::class.java, Visibility.PRIVATE)
.defineField("lastName", String::class.java, Visibility.PRIVATE)
.defineConstructor(Visibility.PUBLIC)
.withParameters(String::class.java, String::class.java)
.intercept(
MethodCall.invoke(Any::class.java.getDeclaredConstructor())
.andThen(FieldAccessor.ofField("firstName").setsArgumentAt(0))
.andThen(FieldAccessor.ofField("lastName").setsArgumentAt(1))
)
.method(ElementMatchers.isToString())
.intercept(MethodDelegation.to(PersonToString::class.java))
.make()
.load(ClassLoader.getSystemClassLoader())
.loaded as Class<*>
object PersonToString {
@JvmStatic
fun stringuifyPerson(
@FieldValue("firstName") fn: String,
@FieldValue("lastName") ln: String): String {
return "$fn $ln is the person's name"
}
}
fun main() {
val person = personClass
.getDeclaredConstructor(String::class.java, String::class.java)
.newInstance("John", "Smith")
println(person::class.java.name)
println(personClass.declaredFields.asList())
println(person.toString())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment