动态代理

78 阅读2分钟

前言

动态代理是一种在编程中设计模式,允许你在运行时创建一个代理对象来替代原始对象,以便在方法调用前后执行额外的逻辑。Android中动态代理使用场景,如:性能监控、AOP和事件处理、权限检查、日志记录。

什么是动态代理

代理对象通常实现与原始对象相同的接口,可以添加自定义的行为。动态代理在运行时生成,不需要在编译时知道原始对象的类型。

原理

  1. InvocationHandler(调用处理器):接口,由开发人员实现。包含方法invoke在代理对象上的方法被调用时会被调用。在invoke方法内,可以自定义方法调用前后执行的逻辑。
  2. Proxy(代理类):Java提供的类,用于创建代理对象。需要传递ClassLoader、一组接口以及一个InvocationHander给Proxy.newProxyInstance方法,然后生成代理对象。
interface MyInterface{
    fun doSomething()
}
class MyImplementation :MyInterface{
    override fun doSomething() {
        println("MyImplementation doSomething call")
    }
}
class MyInvocationHandler(private val realObject:MyInterface):InvocationHandler{
    override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any? {
        println("MyInvocationHandler invoke before call")
        val result = method?.invoke(realObject,*(args?: emptyArray()))
        println("MyInvocationHandler invoke after call")
        return result
    }
}

fun main() {
    val realObject = MyImplementation()
    val proxyObject = Proxy.newProxyInstance(
        MyInterface::class.java.classLoader,
        arrayOf(MyInterface::class.java),
        MyInvocationHandler(realObject)) as MyInterface
    proxyObject.doSomething()
}
输出:
MyInvocationHandler invoke before call
MyImplementation doSomething call
MyInvocationHandler invoke after call

MyInvocationHander拦截了doSomething方法调用,在方法前后添加了额外的逻辑

性能监控

class MyInvocationHandler(private val realObject:MyInterface):InvocationHandler{
    override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any? {
        val startTime = System.currentTimeMillis()
        val result = method?.invoke(realObject,*(args?: emptyArray()))
        val endTime = System.currentTimeMillis()
        val duration = endTime - startTime
        println("Performance ${method?.name} took $duration ms to execute")
        return result
    }
}
输出:
Performance doSomething took 2 ms to execute

事件处理

class ClickHandlerProxy(private val target: View.OnClickListener) : InvocationHandler {
    override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any? {
        if (method?.name == "onClick") {
            Log.d("ClickHandler", "Click event intercepted")
        }
        return method?.invoke(target, *args.orEmpty())
    }
}

        val originalClick = View.OnClickListener {
            Log.d("ClickHandler", "originalClick")
        }
        val proxyObject = Proxy.newProxyInstance(
            originalClick::class.java.classLoader,
            originalClick::class.java.interfaces,
            ClickHandlerProxy(originalClick)
        ) as View.OnClickListener
button.setOnclickListener(proxyObject)
输出:
Click event intercepted
originalClick

在原始点击事件处理逻辑前后执行自定义逻辑,无需修改原始的OnClickListener实现

总结

动态代理,在不修改原始对象情况下添加额外的行为。