动态代理+注释

大家都说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): Any

    /**
     * 进行支付
     */
    @FormUrlEncoded
    @POST("appsdk/Sdk/InternalSubmitOrder")
    fun pay(@FieldMap body: MutableMap): Any

}

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

ServiceProxy.class

class ServiceProxy : InvocationHandler {

    override fun invoke(proxy: Any?, method: Method?, args: Array?): 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  getServiceProxy(clz: Class): T {
        return Proxy.newProxyInstance(clz.classLoader, arrayOf(clz), this) as T
    }

}

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

Test.kt

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

运行结果:


zhushi.jpg

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

你可能感兴趣的:(动态代理+注释)