Java动态代理中如何进行InvocationHandler最简单的入门(invocationhandler,java,编程语言)

时间:2024-04-29 21:50:34 作者 : 石家庄SEO 分类 : 编程语言
  • TAG :

    Java%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E4%B8%AD%E5%A6%82%E4%BD%95%E8%BF%9B%E8%A1%8CInvocationHandler%E6%9C%80%E7%AE%80%E5%8D%95%E7%9A%84%E5%85%A5%E9%97%A8

网上关于Java的动态代理,Proxy和InvocationHandler这些概念有讲解得非常高深的文章。其实这些概念没有那么复杂。现在咱们通过一个最简单的例子认识什么是InvocationHandler。值得一提的是,InvocationHandler在Spring框架实现中被广泛使用,这意味着我们吃透了InvocationHandler,就为将来的Spring源码学习打下一个坚实的基础。

开发一个接口,包含两个方法,可以向指定的人问候“你好”或者“再见”。

创建一个简单的类,实现这个IHello接口。

消费这个实现类,迄今为止没什么特别的。

现在假设我们接到了这个需求:老板要求在该实现类每次问候某人时,必须把问候的细节记录到日志文件里。为了简单起见,我们在问候前打印下面的一行语句来模拟日志记录的动作。

System.out.println("问候之前的日志记录...");

您也许会说,这还不简单?直接修改Helloimplements的对应方法,把这行日志插入到对应方法即可。

Java动态代理中如何进行InvocationHandler最简单的入门

然而,老板的要求是:不允许你修改原来的Helloimplements类。在现实场景中,Helloimplements可能是第三方的jar包提供的,我们没有办法修改代码。

Java动态代理中如何进行InvocationHandler最简单的入门

您也许会说,我们可以用设计模式里的代理模式,即创建一个新的Java类作为代理类,同样实现IHello接口,然后将Helloimplements类的实例传入代理类。我们虽然被要求不允许修改Helloimplements的代码,但是可以把日志记录代码写在代理类里。完整代码如下:

这种做法能够实现需求:

Java动态代理中如何进行InvocationHandler最简单的入门

下面我们再看如何用InvocationHandler实现同样的效果。

上面代码里的bind方法很想我之前代理类StaticProxy的setImpl方法,只不过这个bind方法的输入参数类型更加通用。日志记录的代码写在方法invoke里。

看看如何使用:

执行效果和StaticProxy那种解决方案完全一致。

咱们先来调试一下。当bind方法执行时,方法Proxy.newProxyInstance被调用,Helloimplements类的实例被传入。

Java动态代理中如何进行InvocationHandler最简单的入门

我们在调试器里观察IHello ihello = (IHello) helloproxy.bind(hello)这行语句返回的ihello变量。虽然它的静态类型是IHello,但请注意,在调试器里观察它的实际类型,并不是Helloimplements的实例,而是JVM给我们加过工的,包含了我们在invoke方法里手写的那行日志记录代码。这个ihello类型为$Proxy0。

Java动态代理中如何进行InvocationHandler最简单的入门

当这个被JVM加过工的变量的sayHello方法被调用时,JVM自动将调用转交到DynaProxyHello.invoke去:

Java动态代理中如何进行InvocationHandler最简单的入门

于是,在invoke方法里,我们手写的日志记录代码被执行,然后通过Java反射执行原始的sayHello代码。

有的朋友可能会问,你这个InvocationHandler看起来比静态代理StaticProxy还复杂啊?有什么好处?

假设老板的需求又变了,在调用问候和说再见的方法里,要使用不同的日志记录策略。

看看用InvocationHandler如何优雅实现吧:

Java动态代理中如何进行InvocationHandler最简单的入门

本文:Java动态代理中如何进行InvocationHandler最简单的入门的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:如何实现dedecms列表页单独上一页跟下一页链接下一篇:

7 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18