【问题标题】:Dynamic proxy for suspend methods?挂起方法的动态代理?
【发布时间】:2019-04-20 00:45:08
【问题描述】:

这是我的界面:

interface BlogService {
    suspend fun tag() : JsonObject
}

是否可以为suspend方法创建一个动态代理并在里面运行协程? 我无法使用 jdk 中的“Proxy.newProxyInstance”,因为我收到编译错误(应该从另一个挂起函数运行挂起函数)

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    我遇到了同样的问题。我认为答案是肯定的。这是我想出来的。

    如下界面

    interface IService {
        suspend fun hello(arg: String): Int
    }
    

    编译成这个

    interface IService {
        fun hello(var1: String, var2: Continuation<Int>) : Any
    }
    

    编译后,普通函数和挂起没有区别 函数,除了后者有一个额外的类型参数 Continuation。只需在委托中返回COROUTINE_SUSPENDED InvocationHandler.invoke 如果你真的想暂停它。

    这是一个通过 java 动态代理创建 ISerivce 实例的示例 设施Proxy.newProxyInstance

    import java.lang.reflect.InvocationHandler
    import java.lang.reflect.Proxy
    import kotlin.coroutines.Continuation
    import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED
    import kotlin.coroutines.resume
    
    fun getServiceDynamic(): IService {
        val proxy = InvocationHandler { _, method, args ->
            val lastArg = args?.lastOrNull()
            if (lastArg is Continuation<*>) {
                val cont = lastArg as Continuation<Int>
                val argsButLast = args.take(args.size - 1)
                doSomethingWith(method, argsButLast, onComplete = { result: Int ->
                    cont.resume(result)
                })
                COROUTINE_SUSPENDED
            } else {
                0
            }
        }
        return Proxy.newProxyInstance(
            proxy.javaClass.classLoader,
            arrayOf(IService::class.java),
            proxy
        ) as IService
    }
    

    我相信这段代码 sn-p 足够简单且不言自明。

    【讨论】:

    • 目前还不完全清楚“doSomething”函数的作用,以及“onComplete”函数被调用或传递的位置。我们如何恢复暂停的协程?
    • 我刚刚玩过这段代码,当挂起函数抛出错误时,这似乎不起作用。 JVM 将此错误包装在“UndeclaredThrowable”异常中,然后应该由代理的调用者捕获(这是您不想更改的代码)。
    猜你喜欢
    • 1970-01-01
    • 2016-11-19
    • 2018-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-09
    相关资源
    最近更新 更多