首页IT科技java代理原理(对java中代理的理解笔记)

java代理原理(对java中代理的理解笔记)

时间2025-07-30 20:59:29分类IT科技浏览5195
导读:简单例子 package com.kfm.jdbc.day0328; import...

简单例子

package com.kfm.jdbc.day0328; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public interface Actor { void sing(double money); void jump(double money); } class Kun implements Actor{ @Override public void sing(double money) { System.out.println("收了" + money + "元             ,唱了一首《只因你太美》"); } @Override public void jump(double money) { System.out.println("收了" + money + "元                        ,跳了一个舞"); } } class Agent implements Actor{ private Actor actor; public Agent(Actor actor){ this.actor = actor; } @Override public void sing(double money) { this.actor.sing(money * 0.8); } @Override public void jump(double money) { this.actor.jump(money * 0.9); } } class Main { public static void main(String[] args) { Kun kun = new Kun(); Actor o = (Actor) Proxy.newProxyInstance(Kun.class.getClassLoader(), new Class[]{Actor.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String name = method.getName(); if ("sing".equals(name)){ System.out.println("请他唱歌先请我吃饭"); return method.invoke(kun, args); } else { System.out.println("做其他事得加钱"); return method.invoke(kun, args); } } } ); o.sing(1.1); o.jump(2.2); // Agent agent = new Agent(kun); // agent.sing(50000); } }

对例子进行分析:

有一个actor的接口       ,有jump和sing两个方法 ikun实现了此接口 但是你能直接见到IKUN吗??? 因此需要一个agent也来实现actor接口         ,但是                       ,agent需要赚一点差价 现在在代码每次运行时           ,来一个agent      ,因此就用到代理:

在 Main 类中                      ,首先创建了一个 Kun 对象 kun               ,然后使用 Java 反射机制   ,创建了一个代理对象 o                     ,代理的是 Kun 类                。在代理对象的创建过程中                   ,传入了 Kun 类的类加载器                、Actor 接口的 Class 对象和一个 InvocationHandler 对象                    。这个 InvocationHandler 对象的作用是拦截代理对象方法的调用,对调用进行增强        。在 invoke 方法中                 ,首先判断调用的方法是 sing 还是 jump                       ,如果是 sing 方法   ,则输出一条信息“请他唱歌先请我吃饭                ”             ,然后再调用 kun 对象的 sing 方法            。如果是 jump 方法                        ,则输出一条信息“做其他事得加钱                    ”       ,然后再调用 kun 对象的 jump 方法                    。最后         ,通过代理对象 o 调用了 sing 和 jump 方法           。在这个示例中                       ,代理对象 o 拦截了 sing 和 jump 方法的调用           ,对 sing 方法进行了增强      ,输出了一条信息                      ,而对 jump 方法没有进行增强               ,只是输出了一条提示信息        。

Proxy.newProxyInstance 是 Java 动态代理的一个方法   ,用于创建代理对象                     。它有三个参数:

ClassLoader 类加载器                     ,用于加载代理对象的 Class 文件              。

Class [] interfaces                   ,被代理对象实现的接口列表,这些接口必须是非 final 类型    。

InvocationHandler invocationHandler                 ,实现了 InvocationHandler 接口的对象                       ,用于拦截代理对象的方法调用并进行增强                      。

在这段代码中   ,Kun.class.getClassLoader() 表示使用 Kun 类的类加载器来加载代理对象的 Class 文件                 。new Class[]{Actor.class} 表示要代理的接口列表             ,这里只有 Actor 接口。new InvocationHandler() 表示实现了 InvocationHandler 接口的对象                        ,这里使用了匿名内部类来实现                   。在这个匿名内部类中       ,重写了 invoke 方法         ,用于拦截代理对象的方法调用并进行增强                    。

最后                       ,将代理对象强制转换为 Actor 类型           ,并将其赋值给 o 变量      ,o 可以调用 Actor 接口中的方法                      ,实际上调用的是被代理对象 Kun 的对应方法               ,而 InvocationHandler 中的增强操作也会被执行    。

invoke() 方法是 InvocationHandler 接口中的一个方法   ,用于拦截代理对象的方法调用并进行增强                。它有三个参数:

Object proxy                     ,代理对象本身                   ,通常在 invoke() 方法中不会使用到                    。

Method method,代理对象被调用的方法对象        。

Object[] args                 ,代理对象被调用的方法的参数列表            。

在这段代码中                       ,invoke() 方法首先通过 Method 对象获取被调用方法的名字   ,然后判断被调用的方法是 sing 还是其他方法                    。如果是 sing 方法             ,就输出一句话并调用被代理对象 Kun 的 sing() 方法                        ,并将其返回值作为 invoke() 方法的返回值           。如果是其他方法       ,就输出另一句话并调用被代理对象 Kun 的对应方法         ,并将其返回值作为 invoke() 方法的返回值        。

因此                       ,当代理对象 o 调用 sing() 方法时           ,实际上会调用 invoke() 方法      ,并在其中输出一句话                      ,并调用被代理对象 Kun 的 sing() 方法               ,并将其返回值作为 o.sing() 的返回值                     。当代理对象 o 调用 jump() 方法时   ,实际上也会调用 invoke() 方法                     ,并在其中输出另一句话                   ,并调用被代理对象 Kun 的 jump() 方法,并将其返回值作为 o.jump() 的返回值              。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
王垠github(王垠:不再推荐 Haskell_IT新闻_博客园) linux最小化快捷键(恢复Linux桌面下方面板上显示最小化的图标的方法)