Kotlin 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") } }

考虑以下bytebuddy程序来拦截方法调用
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]