Kotlin 动态代理的使用以及一些坑点

Kotlin 动态代理的使用以及一些坑点,第1张

Kotlin 动态代理的使用以及一些坑点 什么是动态代理如何使用坑点

什么是动态代理

在本文中,讨论的是kotlin中如何使用类似于JDK动态代理的功能,而非kotlin中by关键字实现的代理模式,所以可以说此文是介绍如何用kotlin实现JDK动态代理,至于JDK动态代理是什么,本文不予赘述,读者可自行查阅有关资料。

如何使用

在正式开始使用前,先介绍下几个比较重要的东西

在动态代理中,最重要的是InvocationHandler,因为最终实现代理就是在InvocationHandlerinvoke方法中实现的,InvocationHandler是一个接口,该接口中只有一个invoke方法。要被代理的类必须继承自一个接口,换句话说,要被代理的方法,必须利用接口进行声明。

下面开始正片:

为需要被代理的类及方法创建接口
interface IDemo{
    fun test(action: String, code: Int)
}
创建实现接口的类
class Demo : IDemo{
    override fun test(action: String, code: Int) {
        println("action = [${action}], code = [${code}]")
    }
}
进行代理
fun proxyTest() {
    val demo = Demo() // 创建要被代理的实例
    val proxy = Proxy.newProxyInstance( // 获取实例的代理对象
        Demo::class.java.classLoader, // 获取实例的classloader
        arrayOf(IDemo::class.java), // 实例接口
        object : InvocationHandler {
            override fun invoke(proxy: Any, method: Method, args: Array<out Any>): Any {
                println("before...") // 代理增强方法
                val result = method.invoke(demo, *args) // 反射调用实例的原始方法
                if ("void" == method.genericReturnType.typeName) // 如果返回值为void, 要转换为Unit, 否则会报空指针异常
                    return Unit
                return result
            }
        }) as IDemo // 类型转换
    proxy.test("hello", 123456) // 调用代理
}
输出
before...
action = [hello], code = [123456]
坑点 kotlin直接生成的InvocationHandler,其invoke方法参数类型都是可空的,这里需要手动调整为非空,就是去掉参数类型声明后的?,一般来说这么做是没有问题的,可以参照JDK的InvocationHandler,当然你也可以进行非空判断,至于kotlin为什么将invoke方法的形参类型都变成了可空类型,我也不太清楚,有了解的朋友可以评论区科普一下。返回类型,如果被代理方法的返回类型为void,那么需要在invoke方法中返回UnitProxynewProxyInstance第二个参数必须为接口的class数组,不能是被代理对象的class,否则会报is not interface的异常。

最后,这篇文章属于个人经验,可能存在盲点,欢迎各位指出文中的错误之处!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/992614.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存