首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Bytebuddy:方法拦截在Kotlin中不起作用

Bytebuddy:方法拦截在Kotlin中不起作用
EN

Stack Overflow用户
提问于 2019-01-05 01:04:35
回答 1查看 734关注 0票数 0

考虑下面的bytebuddy程序来拦截方法调用load()

代码语言:javascript
复制
public class ByteJavaBuddyTest {
    public static class MemoryDatabase {
        public List<String> load(String info) {
            return Arrays.asList(info + ": foo", info + ": bar");
        }
    }

    public static class LoggerInterceptor {
        public static List<String> log(@SuperCall Callable<List<String>> zuper) throws Exception {
            System.out.println("Calling database");
            try {
                return zuper.call();
            } finally {
                System.out.println("Returned from database");
            }
        }
    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        MemoryDatabase loggingDatabase = new ByteBuddy()
                .subclass(MemoryDatabase.class)
                .method(named("load")).intercept(MethodDelegation.to(LoggerInterceptor.class))
                .make()
                .load(MemoryDatabase.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
                .getLoaded()
                .getDeclaredConstructor()
                .newInstance();
        System.out.println(loggingDatabase.load("qux"));
    }
}

它运行并打印:

代码语言:javascript
复制
Calling database
Returned from database
[qux: foo, qux: bar]

在转换为Kotlin之后,它不会运行拦截器,也不会抛出任何异常。

代码语言:javascript
复制
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"))
    }
}

打印:

代码语言:javascript
复制
[qux: foo, qux: bar]

因为它没有抛出任何错误,我真的不知道从哪里开始挖掘。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-01-06 02:14:47

Byte Buddy通过重写方法来代理方法。如果一个方法在Kotlin中没有声明为open,那么它在Java字节码中就是final。如果你打开你的方法,你的逻辑应该会再次工作。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54043234

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档