Kotlin Bytebuddy:方法拦截不';我不在科特林工作
考虑以下bytebuddy程序来拦截方法调用Kotlin Bytebuddy:方法拦截不';我不在科特林工作,kotlin,byte-buddy,Kotlin,Byte Buddy,考虑以下bytebuddy程序来拦截方法调用load(): 转换到Kotlin后,它不会运行拦截器,也不会抛出任何异常 object ByteBuddyKotlinTest { open class MemoryDatabase { fun load(info: String): List<String> { return Arrays.asList("$info: foo", "$info: bar") } }
load()
:
转换到Kotlin后,它不会运行拦截器,也不会抛出任何异常
object ByteBuddyKotlinTest {
open class MemoryDatabase {
fun load(info: String): List<String> {
return Arrays.asList("$info: foo", "$info: bar")
}
}
object LoggerInterceptor {
@Throws(Exception::class)
fun log(@SuperCall zuper: Callable<List<String>>): List<String> {
println("Calling database")
try {
return zuper.call()
} finally {
println("Returned from database")
}
}
}
@Throws(
NoSuchMethodException::class,
IllegalAccessException::class,
InvocationTargetException::class,
InstantiationException::class
)
@JvmStatic
fun main(args: Array<String>) {
val loggingDatabase = ByteBuddy()
.subclass(MemoryDatabase::class.java)
.method(ElementMatchers.named("load")).intercept(MethodDelegation.to(LoggerInterceptor::class.java))
.make()
.load(MemoryDatabase::class.java.classLoader, ClassLoadingStrategy.Default.WRAPPER)
.loaded
.getDeclaredConstructor()
.newInstance()
println(loggingDatabase.load("qux"))
}
}
因为它没有抛出任何错误,我真的不知道从哪里开始挖掘 Byte Buddy通过重写方法来代理这些方法。如果一个方法没有在Kotlin中声明为
open
,那么它在Java字节码中是final
。如果打开方法,您的逻辑将再次工作。字节伙伴代理通过重写方法来代理方法。如果一个方法没有在Kotlin中声明为open
,那么它在Java字节码中是final
。如果打开方法,您的逻辑应该会再次工作。添加load open会引发错误:线程“main”java.lang.IllegalArgumentException中的异常:[]中的任何一个都不允许从public java.util.List liquibase.ext.ksharma.change.ByteBuddyKotIntest$MemoryDatabase.load(java.lang.String)进行委派
我假设您的拦截器方法没有编译为公共的和静态的?LoggerInterceptor::class.java声明了哪些方法?您可以使用javap.Ah检查类文件,我认为在对象中放入一个方法会使其成为静态的。但是,您需要在该方法上添加@JvmStatic
注释。现在工作。谢谢你的帮助和很棒的图书馆!您认为它是否应该抛出错误或记录警告,而不是静默失败?它确实抛出了一个异常?添加load open会抛出错误:线程“main”java.lang.IllegalArgumentException中的异常:[]中没有一个允许从public java.util.List liquibase.ext.ksharma.change.ByteBuddyKotIntest$MemoryDatabase.load进行委派(java.lang.String)
我假设您的拦截器方法没有编译为公共的和静态的?LoggerInterceptor::class.java声明了什么方法?您可以使用javap检查类文件。啊,我认为将方法放入对象中会使其成为静态的。但是,您需要为此在方法上添加@JvmStatic
注释。不起作用w、 感谢您的帮助和令人敬畏的库!您认为它是否应该抛出一个错误或记录一个警告,而不是默默地失败?它确实抛出了一个例外?
Calling database
Returned from database
[qux: foo, qux: bar]
object ByteBuddyKotlinTest {
open class MemoryDatabase {
fun load(info: String): List<String> {
return Arrays.asList("$info: foo", "$info: bar")
}
}
object LoggerInterceptor {
@Throws(Exception::class)
fun log(@SuperCall zuper: Callable<List<String>>): List<String> {
println("Calling database")
try {
return zuper.call()
} finally {
println("Returned from database")
}
}
}
@Throws(
NoSuchMethodException::class,
IllegalAccessException::class,
InvocationTargetException::class,
InstantiationException::class
)
@JvmStatic
fun main(args: Array<String>) {
val loggingDatabase = ByteBuddy()
.subclass(MemoryDatabase::class.java)
.method(ElementMatchers.named("load")).intercept(MethodDelegation.to(LoggerInterceptor::class.java))
.make()
.load(MemoryDatabase::class.java.classLoader, ClassLoadingStrategy.Default.WRAPPER)
.loaded
.getDeclaredConstructor()
.newInstance()
println(loggingDatabase.load("qux"))
}
}
[qux: foo, qux: bar]