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

本文介绍了如何在Kotlin中使用JDK动态代理,强调了InvocationHandler的重要性和代理过程。创建接口IDemo与其实现类Demo,然后通过Proxy.newProxyInstance创建代理对象。在代理过程中,注意返回类型处理和接口类数组的使用。文章还提到了动态代理的一些坑点,如invoke方法参数类型的非空调整和void返回类型需转为Unit。
摘要由CSDN通过智能技术生成

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

什么是动态代理

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

如何使用

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

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

下面开始正片:

  1. 为需要被代理的类及方法创建接口
    interface IDemo{
        fun test(action: String, code: Int)
    }
    
  2. 创建实现接口的类
    class Demo : IDemo{
        override fun test(action: String, code: Int) {
            println("action = [${action}], code = [${code}]")
        }
    }
    
  3. 进行代理
    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) // 调用代理
    }
    
  4. 输出
    before...
    action = [hello], code = [123456]
    

坑点

  1. kotlin直接生成的InvocationHandler,其invoke方法参数类型都是可空的,这里需要手动调整为非空,就是去掉参数类型声明后的?,一般来说这么做是没有问题的,可以参照JDK的InvocationHandler,当然你也可以进行非空判断,至于kotlin为什么将invoke方法的形参类型都变成了可空类型,我也不太清楚,有了解的朋友可以评论区科普一下。
  2. 返回类型,如果被代理方法的返回类型为void,那么需要在invoke方法中返回Unit
  3. ProxynewProxyInstance第二个参数必须为接口的class数组,不能是被代理对象的class,否则会报is not interface的异常。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kotlin代理模式,也称为动态代理或依赖注入(Dependency Injection)的一种形式,主要用于创建一个代理对象,这个代理对象可以在运行时动态地拦截对目标对象的调用,并执行额外的操作。它常见于需要增强功能、实施AOP(面向切面编程)或者处理事务管理等场景。 使用场景包括但不限于: 1. **性能监控**:可以记录每个方法的调用时间,计数等统计数据。 2. **日志记录**:在方法调用前后添加日志信息。 3. **权限验证**:检查用户是否有执行某个操作的权限。 4. **缓存优化**:通过代理,在访问数据库之前先从缓存中获取数据。 下面是一个简单的Kotlin代理模式的示例: ```kotlin import kotlin.reflect.KClass // 定义一个基础的接口 interface Service { fun doSomething() } // 使用Proxy.create创建代理类 fun <T : Any> createProxy(serviceClass: KClass<T>): T { return object : Proxy() as T { override fun invoke(interceptor: MethodCall): Any? { val method = serviceClass.memberMethodByName(interceptor.name) val args = interceptor.arguments.map { it.value } val result = method.invoke(null, *args) println("Before $method") // 执行实际业务逻辑 val returnedResult = method.invoke(this, *args) println("After $method") return returnedResult } } } fun main() { val service: Service = createProxy(Service::class.java) service.doSomething() } ``` 在这个例子中,`createProxy`函数创建了一个代理,当调用`doSomething`方法时,会先打印出"Before"和"After"的日志信息。这就是Kotlin代理模式的一个基本应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值