Java动态代理

在之前空对象模式一文中,讨论约束空对象方法调用时,提到可以使用 动态代理
实现。复用前文的数据模型,现在就来实现这个方式。而动态代理的具体运行逻辑详情,将在以后文章单独进行源码剖析。

和静态代理一样,动态代理也需要把所有行为抽象化,于是把以前写在 User
的行为全部抽象到接口 IUser

interface IUser{
    fun getUserId(): String

    fun getRoomId(): String

    fun getRemark(): String
}

然后 User
模型实现该抽象接口

class User(private val userId: String,
           private val roomId: String,
           private val nickname: String) : IUser {

    override fun getUserId(): String {
        return userId
    }

    override fun getRoomId(): String {
        return roomId
    }

    override fun getRemark(): String {
        return nickname
    }
}

实现动态代理的关键是实现 InvocationHandler
。使用动态代理,是为了把所有方法代理到同一实例中,所以实现 InvocationHandler
时还需要提供有参构造方法,让外部传入接收委托的实例。

不过,这次并不需要委托任何行为,而只是通过动态代理这个中转,以抛出异常的方式阻止实例里所有方法的调用。由以下代码可见,该中介类无需保存被委托类实例,只是在实现方法里抛异常阻止调用。

class Handler : InvocationHandler {
    // 实现唯一的抽象方法
    override fun invoke(proxy: Any, method: Method, args: Array<out Any>): Any {
        // 抛出异常
        throw IllegalAccessException("Access to this method is denied.")
    }
}

实现中介类 InvocationHandler
之后就可以创建实例。按照惯例,空对象单例对象一般和其模型放在一起。

class User(private val userId: String,
           private val roomId: String,
           private val nickname: String) : IUser {

    .....

    companion object {
        val defUser by lazy {
            // 创建空对象实例,这个实例里所有方法已被代理
            Proxy.newProxyInstance(
                    IUser::class.java.classLoader,
                    arrayOf(IUser::class.java),
                    Handler()) as IUser
        }
    }
}

这个被代理的实例使用方式和普通对象无异

object ProxyRunner {
    @JvmStatic fun main(args: Array<String>) {
        User.defUser.getRemark()
    }
}

只在运行时走代理逻辑,然后主动抛出预定实现的异常:

Exception in thread "main" java.lang.reflect.UndeclaredThrowableException
	at com.sun.proxy.$Proxy0.getRemark(Unknown Source)
	at proxy.ProxyRunner.main(ProxyRunner.java:6)
Caused by: java.lang.IllegalAccessException: Access to this method is denied.
	at proxy.Handler.invoke(Handler.kt:8)
	... 2 more
  • 上一篇

    5个线程先打印Hello再打印world

原文 

http://phantomvk.coding.me/2019/04/06/Java_Dynamic_Proxy/

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » Java动态代理

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址