java代理原理(对java中代理的理解笔记)
简单例子
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版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!