美文网首页
动态代理+注释

动态代理+注释

作者: 王灵 | 来源:发表于2022-10-19 16:39 被阅读0次

    大家都说retrofit的经典之处就在于动态代理+注释,于是我专门去了解了动态代理和注解。下面开始我的猜想,retrofit的源码太复杂了我看不懂。

    1、利用注释创建3个retrofit中的常见自定义注释

    FormUrlEncoded.class

    @Documented //标记这些注释是否包含在用户文档中
    @Target({ElementType.METHOD})//注释用在哪里 方法
    @Retention(RetentionPolicy.RUNTIME)//注释怎么保存  RUNTIME*运行时
    public @interface FormUrlEncoded {
    }
    

    POST.class

    @Documented //文档
    @Target({ElementType.METHOD})//方法
    @Retention(RetentionPolicy.RUNTIME)//运行时
    public @interface POST {
        String value() default "";
    }
    

    FieldMap.class

    @Documented //文档
    @Target({ElementType.PARAMETER})//参数
    @Retention(RetentionPolicy.RUNTIME)//运行时
    public @interface FieldMap {
        boolean encoded() default false;
    }
    

    2、创建一个接口类来使用上门的注释,模拟开发中的请求接口定义

    PayService.class

    interface PayService {
        /**
         * 获取支付配置
         */
        @FormUrlEncoded
        @POST("appsdk/Sdk/GetPayment")
        fun getPayConfig(@FieldMap body: MutableMap<String, Any>): Any
    
        /**
         * 进行支付
         */
        @FormUrlEncoded
        @POST("appsdk/Sdk/InternalSubmitOrder")
        fun pay(@FieldMap body: MutableMap<String, Any>): Any
    
    }
    

    3、创建动态代理类,并获取对应函数中的注解信息

    ServiceProxy.class

    class ServiceProxy : InvocationHandler {
    
        override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any {
            //获取函数的注释
            if (method?.isAnnotationPresent(FormUrlEncoded::class.java) == true) {
                println("函数有 FormUrlEncoded 注释")
            }
            if (method?.isAnnotationPresent(POST::class.java) == true) {
                var annotation = method.getAnnotation(POST::class.java)
                println("函数有 POST 注释 Value:" + annotation.value)
            }
            method?.apply {
                var parameterAnnotations = parameterAnnotations
    
                parameterAnnotations.forEach {
                    it.forEach { annotation ->
                        println(annotation)
                        if (annotation.annotationClass.simpleName == FieldMap::class.java.simpleName) {
                            println("参数上有 FieldMap 注释")
                        }
                    }
                }
            }
            return ""//获取到需要的信息之后,完全可以组合成okhttp请求需要的各种参数
        }
    
        public fun <T> getServiceProxy(clz: Class<T>): T {
            return Proxy.newProxyInstance(clz.classLoader, arrayOf(clz), this) as T
        }
    
    }
    

    4、创建一个测试类,来看看能否获取到我们想要的信息

    Test.kt

    object Test {
        @JvmStatic
        fun main(args: Array<String>) {
            val map = mutableMapOf<String, Any>(
                "amount" to "",
                "billno" to ""
            )
            ServiceProxy().getServiceProxy(PayService::class.java).let {
                    it.getPayConfig(map)
                    it.pay(map)
            }
        }
    }
    

    运行结果:


    zhushi.jpg

    既然能获取到注释的信息,那么我想我们就能利用代理的特效添加后置操作来请求okhttp了。

    相关文章

      网友评论

          本文标题:动态代理+注释

          本文链接:https://www.haomeiwen.com/subject/bggezrtx.html