Java静态代理InvocationHandler和Proxy学习手记转载
原创java动态代理机制中有两个重要的类和接口。InvocationHandler(接口)和Proxy(班),这一班Proxy和接口InvocationHandler是我们实现动态代理的核心;
1.InvocationHandler接口是proxy代理实例的调用处理程序分别实现一个接口。proxy代理实例具有关联的调用处理程序;invoke方法。
看看官方文件InvocationHandler界面说明:
{@code InvocationHandler} is the interface implemented by
the invocation handler of a proxy instance.
Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the {@code invoke} method of its invocation handler. 每个动态代理类的调用处理程序必须实现InvocationHandler接口,并且代理类的每个实例都与实现该接口的动态代理类调用处理程序相关联,当我们通过动态代理对象调用方法时,对该方法的调用将转发给实现。InvocationHandler接口类的invoke要调用的方法,请参见下文。invoke方法: /** * proxy:代理类代理的真实代理对象。com.sun.proxy.$Proxy0 * method:我们想调用对象的真实方法。Method对象 * args:指代理对象方法传递的参数。 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; 2.Proxy类是用于创建代理对象的类,它提供了许多方法,但我们使用最多的是。newProxyInstance方法。 public static Object newProxyInstance(ClassLoader loader, Class>[] interfaces, InvocationHandler h) Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler. This method is equivalent to: 该方法的功能是创建一个代理类对象,它接收三个参数。让我们看看以下参数的含义: loader:一个classloader对象,它定义了classloader对象加载生成的代理类。 interfaces:一个interface对象数组表示我们将向代理对象提供的接口集。如果我们提供这样一个接口对象数组,那么将声明代理类来实现这些接口,并且代理类可以调用接口中声明的所有方法。 h:一个InvocationHandler对象,表示动态代理对象调用方法时关联的对象。InvocationHandler对象,并最终由其调用。 3上面已经介绍了动态代理中的两个核心接口和类。接下来,我们将使用示例来理解具体用法。 首先我们定义一个接口People package reflect; public interface People { public String work(); } 定义一个Teacher类,实现People接口,这个类是一个真实的对象。 package reflect; public class Teacher implements People{ @Override public String work() { System.out.println("教师教书育人..."); return "教书"; } } 现在我们要定义一个代理类调用处理程序,每个代理类调用处理器都必须实现。InvocationHandler接口,代理类如下: package reflect; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class WorkHandler implements InvocationHandler{ //代理类中的真实对象 private Object obj; public WorkHandler() { // TODO Auto-generated constructor stub } //构造函数,为实际对象赋值 public WorkHandler(Object obj) { this.obj = obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //我们可以在实际对象执行之前添加自己的操作。 System.out.println("before invoke。。。"); Object invoke = method.invoke(obj, args); //我们可以在实际对象执行后添加自己的操作。 System.out.println("after invoke。。。"); return invoke; } } 上面的代理类调用处理程序invoke方法中的第一个参数proxy似乎我们以前从未使用过它,请参阅我的另一篇文章了解此参数的具体用法和含义。Java中InvocationHandler界面中的第一个参数proxy详解 接下来,让我们看看客户端类。 package reflect; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Test { public static void main(String[] args) { //要表示的真实对象 People people = new Teacher(); //代理对象的调用处理程序,我们将要表示的真实对象传入代理对象的调用处理的构造函数中,最终代理对象的调用处理程序会调用真实对象的方法 InvocationHandler handler = new WorkHandler(people); /** * 通过Proxy类的newProxyInstance方法来创建代理对象,让我们看看方法中的参数。 * 第一个参数:people.getClass().getClassLoader(),使用handler对象的classloader对象加载代理对象。 * 第二个参数:people.getClass().getInterfaces(),这里为代理类提供的接口是由真实对象实现的接口,因此代理对象可以像真实对象一样调用接口中的所有方法。 * 第三个参数:handler,我们将代理对象与上面的InvocationHandler对象上 */ People proxy = (People)Proxy.newProxyInstance(handler.getClass().getClassLoader(), people.getClass().getInterfaces(), handler); //System.out.println(proxy.toString()); System.out.println(proxy.work()); } } 查看输出: before invoke。。。 教师教书育人... after invoke。。。 教书 通过以上的解释和实例,说明了动态代理的原理和使用方法。Spring中的两个核心IOC和AOP中的AOP(面向面编程)的思想就是动态代理,在代理类的前面和后面加上不同的切面组成面向面编程。 我们只在上面解释了Proxy中的newProxyInstance(用于生成代理类的方法),但它有其他几种方法,我们将在下面描述: getInvocationHandler:返回指定代理实例的调用处理程序。 getProxyClass:给定类加载器和接口数组的代理类。java.lang.Class对象。 isProxyClass:当且仅当使用getProxyClass方法或newProxyInstance只有当指定的类作为代理类动态生成时,该方法才会返回。true。 newProxyInstance:返回指定接口的代理类的实例,该接口将方法调用分派给指定的调用处理程序。 --------------------- 作者:随风yy 来源:CSDN 原文:https://blog.csdn.net/yaomingyang/article/details/80981004 版权声明:本文为博主原创文章。转载请附上博客链接!
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除