java Proxy InvocationHandler 动态代理实现详解
spring 两大思想,其一是IOC,其二就是AOP..而AOP的原理就是java 的动态代理机制。这里主要记录java 动态代理的实现及相关类的说明。
java 动态代理机制依赖于InvocationHandler接口、Proxy类。这是java 实现动态代理必须用到的。
一、InvocationHandler:该接口中只有一个方法 public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;
该方法的作用目标对象的方法会转发由InvocationHandle这个接口的invoke方法来调用
/** * invoke 是 InvocationHandler 接口的唯一方法 * 当我们使用动态代理调用目标对象的方法时,
* 目标对象的方法会转发由InvocationHandle这个接口的invoke方法来调用 * 参数 1、proxy ==> 代理的目标对象 * 2、method ==> 目标对象要调用的方法 * 3、args ==> 目标对象要调用的方法的参数数据 * */
以下是源码对invoke方法的解释
/** * Processes a method invocation on a proxy instance and returns * the result. This method will be invoked on an invocation handler * when a method is invoked on a proxy instance that it is * associated with. */
二、Proxy:Proxy类的作用及时动态创建一个代理对象的类,Proxy提供了许多方式,用了最多的是newProxyInstance
/** * * @param target * @return * * Proxy.newProxyInstance(loader, interfaces, h) 说明: * Proxy类的作用及时动态创建一个代理对象的类,Proxy提供了许多方式,用了最多的是newProxyInstance * 参数 1、loader ==> 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载 * 2、interfaces ==> 一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口, * 如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了 * 3、h ==> 一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候, * 会关联到哪一个InvocationHandler对象上 * * */
以下是源码的解释
/** * Returns an instance of a proxy class for the specified interfaces * that dispatches method invocations to the specified invocation * handler. */
三、动态代理的实现
1、创建布标对象的接口Hello.java
/** * java proxy InvocationHandler 动态代理公共接口 * * @author dyf * */ public interface Hello { void sayHello(); void run(String name,int count); }
2、创建代理类DynaProxy.java
package cn.dyf.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * java proxy InvocationHandler 实现公共接口代理对象 * 动待代理对象需实现InvocationHandler接口,重新invoke方法 * @author dyf * */ public class DynaProxy implements InvocationHandler{ private Object target; /** * * @param target * @return * * Proxy.newProxyInstance(loader, interfaces, h) 说明: * Proxy类的作用及时动态创建一个代理对象的类,Proxy提供了许多方式,用了最多的是newProxyInstance * 参数 1、loader ==> 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载 * 2、interfaces ==> 一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口, * 如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了 * 3、h ==> 一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候, * 会关联到哪一个InvocationHandler对象上 * * */ public Object bind(Object target) { this.target = target; return Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), this); } /** * invoke 是 InvocationHandler 接口的唯一方法 * 当我们使用动态代理调用目标对象的方法时,目标对象的方法会转发由InvocationHandle这个接口的invoke方法来调用 * 参数 1、proxy ==> 代理的目标对象 * 2、method ==> 目标对象要调用的方法 * 3、args ==> 目标对象要调用的方法的参数数据 * */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; result = method.invoke(this.target, args); return result; } }
3、创建App测试类
package cn.dyf.proxy; public class ProxyApp { public static void main(String[] args) { // new StaticProxy(new SjHello()).sayHello(); Hello bind = (Hello)new DynaProxy().bind(new SjHello()); bind.sayHello(); bind.run("小明", 100); } }