【问题标题】:InvocationHandler in KotlinKotlin 中的调用处理程序
【发布时间】:2021-09-26 23:23:35
【问题描述】:

我正在阅读 Head First: Design Patterns (2nd ed),我遵循了代码示例,但我没有使用 Java,而是使用了 Kotlin。目前,我正在讨论代理保护模式以及难以使用 Kotlin 运行它的章节。请参阅下面的代码和异常。

示例代码

interface Person {
    fun getName(): String
    fun setName(name: String)
}

class PersonImpl : Person {
    private var _name: String = ""
    override fun getName(): String = _name
    override fun setName(name: String) {
        _name = name
    }
}
class OwnerInvocationHandler(private val person: Person) : InvocationHandler {
    override fun invoke(proxy: Any?, method: Method, args: Array<Any>?): Any? {
        try {
            val methodName = method.name
            if (methodName.isNullOrEmpty())
                return null

            if (methodName.startsWith("get")) {
//              return method.invoke(proxy, *(args ?: arrayOfNulls<Any>(0))) // << Encountered "EXCEPTION B" below
//              return method.invoke(proxy, *(args ?: emptyArray()))         // << Encountered "EXCEPTION B" below
//              return method.invoke(proxy, *args.orEmpty())                 // << Encountered "EXCEPTION B" below
                return method.invoke(proxy, args)                            // << From the code sample, encountered "EXCEPTION A" below
            } else if (methodName.startsWith("set")) {
                return method.invoke(person, args)
            }
        } catch (e: InvocationTargetException) {
            e.printStackTrace()
        }
        return null
    }
}
// main.kt
val listOfPeople = arrayListOf<Person>()

fun main(array: Array<String>) {
    initializeDatabase()

    val joe = getPersonFromDatabase("Joe Javabean") ?: return
    val ownerProxy = getOwnerProxy(joe)
    println("Name is ${ownerProxy.getName()}")

}

fun initializeDatabase() {
    val p1 = PersonImpl()
    p1.setName("Joe Javabean")
    listOfPeople.add(p1)
}

fun getOwnerProxy(person: Person): Person {
    return Proxy.newProxyInstance(
            person.javaClass.classLoader,
            person.javaClass.interfaces,
            OwnerInvocationHandler(person)
    ) as Person
}

fun getPersonFromDatabase(name: String): Person? {
    return listOfPeople.firstOrNull { p -> name.contentEquals(p.getName()) }
}

异常

异常 A

/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x10a5ef4e0). One of the two will be used. Which one is undefined.
Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.helloworld.app.OwnerInvocationHandler.invoke(OwnerInvocationHandler.kt:17)
    at com.sun.proxy.$Proxy0.getName(Unknown Source)
    at com.helloworld.app.MainKt.main(main.kt:12)

异常 B

objc[64094]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/bin/java (0x109e744c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x109eee4e0). One of the two will be used. Which one is undefined.
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at JPLISAgent.c line: 844
java.lang.reflect.InvocationTargetExceptionjava.lang.reflect.InvocationTargetException
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.helloworld.app.OwnerInvocationHandler.invoke(OwnerInvocationHandler.kt:17)
    at com.sun.proxy.$Proxy0.getName(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.helloworld.app.OwnerInvocationHandler.invoke(OwnerInvocationHandler.kt:17)
    at com.sun.proxy.$Proxy0.getName(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.helloworld.app.OwnerInvocationHandler.invoke(OwnerInvocationHandler.kt:17)
    at com.sun.proxy.$Proxy0.getName(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.helloworld.app.OwnerInvocationHandler.invoke(OwnerInvocationHandler.kt:17)
    at com.sun.proxy.$Proxy0.getName(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    ...

我找到了下面的链接,但没有解决我的问题。

Kotlin: Argument Type Mismatch when passing Array as vararg parameter

【问题讨论】:

  • 您不是要调用method.invoke(person, args) 而不是method.invoke(proxy, args)吗?
  • 天啊!谢谢!我不知道我是怎么错过的,显然这只是一个错字。

标签: kotlin design-patterns proxy-pattern


【解决方案1】:

这只是一个用户错误(尴尬)。正如@broot 指出的那样:

代码示例

class OwnerInvocationHandler(private val person: Person) : InvocationHandler {
    override fun invoke(proxy: Any?, method: Method, args: Array<Any>?): Any? {
        try {
            val methodName = method.name
            if (methodName.isNullOrEmpty())
                return null

            if (methodName.startsWith("get")) {
//              return method.invoke(proxy, *(args ?: arrayOfNulls<Any>(0))) // << Encountered "EXCEPTION B" below
//              return method.invoke(proxy, *(args ?: emptyArray()))         // << Encountered "EXCEPTION B" below
//              return method.invoke(proxy, *args.orEmpty())                 // << Encountered "EXCEPTION B" below
//              return method.invoke(proxy, args)                            // << From the code sample, encountered "EXCEPTION A" below
                // `person` should be used not `proxy`
                return method.invoke(person, *args.orEmpty())
            } else if (methodName.startsWith("set")) {
                return method.invoke(person, args)
            }
        } catch (e: InvocationTargetException) {
            e.printStackTrace()
        }
        return null
    }
}

【讨论】:

    猜你喜欢
    • 2022-01-18
    • 2023-02-21
    • 1970-01-01
    • 1970-01-01
    • 2020-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多