0%

动态代理

什么是动态代理?

动态是指运行时动态创建某些接口的实例对象,当调用接口方法时会被分发到InvocationHandler的invoke方法中,代理是指动态创建的接口实例对象可以对某个对象做代理,进行hook等操作

应用场景

  • 为接口添加统一逻辑处理
  • 结合反射动态替换接口实现
  • 面向切面编程

为接口做统一逻辑处理

使用动态代理生成实现某个接口代理对象然后在invocationHandler中做通用逻辑处理,例如Retrofit中巧妙利用动态代理实现网络请求

简化版代码示例

fun main(args: Array<String>) {
// 代理接口
proxyInterface()
}

private fun proxyInterface() {
val httpClient = HttpClient.Builder().build()
httpClient.create(Api::class.java).request()
}

class HttpClient {
class Builder {
fun build(): HttpClient {
return HttpClient()
}
}

@Suppress("UNCHECKED_CAST")
fun <T> create(server: Class<T>): T {
return Proxy.newProxyInstance(server.classLoader, arrayOf(server)) { proxy, method, args ->
println("proxy ${method.name}")
} as T
}
}

/**
* 请求接口
*/
interface Api {
fun request()
}

打印结果

proxy request

Process finished with exit code 0

结合反射动态替换接口实现

通过反射替换静态成员对象为动态代理对象(实现了同样的接口),从而实现hook,对静态成员操作一次操作终身受用😭

在Android系统低版本(好像是8.0以前),AMS获取是通过ActivityManagerNative的getDefault方法获取的,getDefault返回的是ActivityManagerNative静态成员gDefault,某些插件化框架通过动态代理生IActivityManager代理对象并反射替换gDefault,实现对ActivityManagerNative的hook

简化版示例代码

fun main(args: Array<String>) {
// 代理hook
proxyForHook()
}

private fun proxyForHook() {

val proxy = Proxy.newProxyInstance(
IActivityManager::class.java.classLoader, arrayOf(IActivityManager::class.java)
) { proxy, method, args ->
println("proxy activitymanager")
}

val mInstanceField = Class.forName("Singleton").getDeclaredField("mInstance")
mInstanceField.isAccessible = true
val gDefaultField = Class.forName("ActivityManagerNative").getDeclaredField("gDefault")
gDefaultField.isAccessible = true
val gDefault = gDefaultField.get(null)
mInstanceField.set(gDefault, proxy)
ActivityManagerNative.getDefault()?.startActivity()
}


class ActivityManagerNative {
companion object {
@JvmStatic
private val gDefault = object : Singleton<IActivityManager>() {
override fun create(): IActivityManager {
return ActivityManager()
}

}

fun getDefault(): IActivityManager? = gDefault.get()
}


}

interface IActivityManager {
fun startActivity()
}

class ActivityManager : IActivityManager {

override fun startActivity() {
println("start Activity")
}
}


abstract class Singleton<T> {
private var mInstance: T? = null
protected abstract fun create(): T
fun get(): T? {
synchronized(this) {
if (mInstance == null) {
mInstance = create()
}
return mInstance
}
}
}

打印结果

proxy activitymanager

Process finished with exit code 0

面向切面编程

另外动态代理还可以用来做Aop面向切面编程,例如需要在被代理对象执行某个操作前后添加其他操作例如打印日志

示例代码

fun main(args: Array<String>) {
// 代理AOP
proxyForAop()
}

fun proxyForAop() {
val person = Person()
val personProxyHandler = PersonProxyHandler(person)
val personProxy = Proxy.newProxyInstance(
person.javaClass.classLoader,
arrayOf(IAnimal::class.java),
personProxyHandler
) as IAnimal
personProxy.eat()
}

class PersonProxyHandler(private val person: Person) : InvocationHandler {

override fun invoke(proxy: Any?, method: Method, args: Array<out Any>?): Any {
println("doSomething before eat")
method.invoke(person)
println("doSomething after eat")
return Unit
}

}

class Person : IAnimal {
override fun eat() {
println("start eat")
}

}

interface IAnimal {
fun eat()
}

打印结果

doSomething before eat
start eat
doSomething after eat

Process finished with exit code 0