Kotlin--›初识Android Proxy接口动态代理
程序员文章站
2022-06-18 11:22:22
...
接口
的动态代理, 使用这个技术最多的就是Retrofit
框架了.
首先要注意: 动态代理
只能代理接口
,也就是interface
声明的类
如果你想代理class
对象, 可以参考: http://weishu.me/2016/01/28/understand-plugin-framework-proxy-hook/
否则会抛异常:
Caused by: java.lang.IllegalArgumentException: com.angcyo.proxydemo.Target is not an interface
at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:589)
at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:566)
at java.lang.reflect.WeakCache$Factory.get(WeakCache.java:230)
at java.lang.reflect.WeakCache.get(WeakCache.java:127)
at java.lang.reflect.Proxy.getProxyClass0(Proxy.java:419)
at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:820)
at com.angcyo.proxydemo.MainActivity.onCreate(MainActivity.kt:18)
at android.app.Activity.performCreate(Activity.java:6975)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
1:声明一个需要代理的接口
interface ITarget {
fun testFun1()
fun testFun2(arg1: String, arg2: List<String>)
fun testFun3(arg1: String, arg2: List<String>): String
fun testFun4(arg1: String, arg2: ArrayList<String>): String
}
2:接口的默认实现
class Target : ITarget {
override fun testFun4(arg1: String, arg2: ArrayList<String>): String {
Log.i("angcyo", "log fun4")
return "fun4"
}
override fun testFun1() {
Log.i("angcyo", "log fun1")
}
override fun testFun2(arg1: String, arg2: List<String>) {
Log.i("angcyo", "log fun2")
}
override fun testFun3(arg1: String, arg2: List<String>): String {
Log.i("angcyo", "log fun3")
return "fun3"
}
}
之后, 我们用动态代理技术, 可以拦截所有的方法请求
.
你可以任意修改返回值, 或者执行其他操作;
3.创建动态代理
//代理 target 对象, 拦截真实对象的操作, 做自己想做的事
val proxy = Proxy.newProxyInstance(this.classLoader, arrayOf(ITarget::class.java)) { proxy, method, args ->
if (method.name == "toString") {
null
} else {
Log.i("angcyo", "调用方法:$method 返回类型:${method.returnType}")
args?.let {
for (any in it) {
Log.i("angcyo", "参数类型:" + any.javaClass.simpleName)
}
}
if (method.name == "testFun4") {
method.invoke(oldTarget, *args)
}
}
null
}
创建好了代理对象之后, 将代理对象强制赋值给原来的对象.
//通常情况下, 都是采用反射的方式, 用新的代理对象替换原来的真实对象.
val targetField = this.javaClass.getDeclaredField("target")
targetField.isAccessible = true
targetField.set(this, proxy)
之后, 调用对象的方法, 就会被代理对象拦截并执行.
fun onTest(view: View) {
//之后调用对象的方法, 都会被代理类执行
target.testFun1()
target.testFun2("fun2", listOf("1", "2"))
val res3 = target.testFun3("fun3", listOf("a", "b", "c"))
Log.i("angcyo", "result:" + res3)
val res4 = target.testFun4("fun4", arrayListOf("1", "2"))
Log.i("angcyo", "result:" + res4)
}
源码地址: https://github.com/angcyo/ProxyDemo
也许你还想学习更多, 来我的群吧, 我写代码的能力, 远大于写文章的能力:
联系作者
请使用QQ扫码加群, 小伙伴们都在等着你哦!
关注我的公众号, 每天都能一起玩耍哦!
上一篇: 二.cglib实现动态代理
下一篇: yAssistSe.exe是什么进程