Java反射10 : 代理Proxy学习示例
2018-03-04 15:33
525 查看
超级通道: Java泛型学习系列-绪论
java.lang.reflect.Proxy类提供了用于获取和操作代理的静态方法。
如何通过new方法为一个接口创建动态代理实例?
如何获取一个代理实例的调用处理器(InvocationHandler)?如何通过调用处理器(InvocationHandler)调用方法?
如何判断一个类是否是代理类?
如何获取一个代理类?
如何通过代理的构造器创建动态代理实例?
通过代理,可以在运行期动态的创建接口的实现,从而达到解耦的目的。
Proxy代理类只能针对接口(interface)创建代理。
在Proxy类中,有成员变量InvocationHandler(调用处理器),所有对动态代理对象的方法调用都会被转向到InvocationHandler接口的实现上。
Proxy代理类应用广泛,在
通过Proxy.newProxyInstance(interface.class.getClassLoader,interface.class[],handler)创建代理实例
第一个参数是被代理接口的class loader,作为定义这个代理的类加载器。
第二个参数是被代理接口的数组,作为这个代理类要实现的接口
第三个参数是调用处理器(InvocationHandler)的实现类,所有通过这个代理调用的方法实际上都是调用这个实现类的invoke方法。
注意类型转换。
通过Proxy.getInvocationHandler(proxyInstance)获取指定代理的调用处理器
参数为代理对象
通过InvocationHandler实现类的invoke()方法可以进行方法调用。
通过InvocationHandler实现类的invoke()方法,实现各类应用,如:
通过Proxy.isProxyClass(clazz)判断是否是代理类
通过Proxy.getProxyClass(interface.class.getClassLoader(),interface.class)获取代理类对象
第一个参数是被代理接口的class loader,作为定义这个代理的类加载器。
第二个参数是被代理接口的数组,作为这个代理类要实现的接口
通过proxyClass.getConstructor(InvocationHandler.class).newInstance(invocationHandler)创建代理实例
上面提到的通过Proxy.newProxyInstance(…)创建代理实例实际上就是通过proxyClass.getConstructor创建代理实例的分解。
java.lang.reflect.Proxy类提供了用于获取和操作代理的静态方法。
1.通过Proxy可以做什么
通过Proxy可以做以下事情:如何通过new方法为一个接口创建动态代理实例?
如何获取一个代理实例的调用处理器(InvocationHandler)?如何通过调用处理器(InvocationHandler)调用方法?
如何判断一个类是否是代理类?
如何获取一个代理类?
如何通过代理的构造器创建动态代理实例?
2.代理相关
通过Proxy代理类的静态方法,可以为接口创建动态代理实例。通过代理,可以在运行期动态的创建接口的实现,从而达到解耦的目的。
Proxy代理类只能针对接口(interface)创建代理。
在Proxy类中,有成员变量InvocationHandler(调用处理器),所有对动态代理对象的方法调用都会被转向到InvocationHandler接口的实现上。
Proxy代理类应用广泛,在
数据库连接、
事务管理、
拦截器中都使用了动态代理。
3.代码实例
/** * <p>java.lang.reflect.Proxy示例</p> * * @author hanchao 2018/2/28 21:45 **/ public class ReflectProxyDemo { private static final Logger LOGGER = Logger.getLogger(ReflectProxyDemo.class); /** * <p>示例 接口(动态代理只能代理接口)</p> * * @author hanchao 2018/2/28 22:04 **/ interface MyService { void print(); void save(); } /** * <p>示例 类</p> * * @author hanchao 2018/2/28 22:05 **/ static class MyServiceImpl implements MyService { @Override public void print() { LOGGER.info("MyServiceImpl打印信息..."); } @Override public void save() { LOGGER.info("MyServiceImpl保存数据..."); } } /** * <p>示例 调用处理器</p> * * @author hanchao 2018/2/28 22:05 **/ static class MyInvocationHandler implements InvocationHandler { /** * 被代理的对象 */ private Object proxiedObj; public MyInvocationHandler(Object object) { this.proxiedObj = object; } /** * 代理类的调用方法 * * @param proxy 代理对象本身,用于反射获取信息或者连续代理 * @param method 调用的方法 * @param args 调用方法的参数 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //如果是print方法,则直接打印 if ("print".equals(method.getName())) { LOGGER.info("调用了MyInvocationHandler.invoke(proxy,method,args)...不需要事务控制..."); method.invoke(proxiedObj, args); } //如果是save方法,则需要进行事务控制 if ("save".equals(method.getName())) { LOGGER.info("调用了MyInvocationHandler.invoke(proxy,method,args)...需要事务控制..."); LOGGER.info("~~~~~~~~~~~~~~~~开启事务~~~~~~~~~~~~~~~~"); method.invoke(proxiedObj, args); LOGGER.info("~~~~~~~~~~~~~~~~提交或回滚事务(commit/rollback等)~~~~~~~~~~~~~~~~"); } return proxy; } } /** * <p>Java反射-代理Proxy 示例</p> * * @author hanchao 2018/2/28 21:45 **/ public static void main(String[] args) throws Throwable { /** * 在Proxy类中,有成员变量:protected InvocationHandler h; * InvocationHandler是 代理实例 的调用处理程序 */ /*创建一个接口的 代理实例*/ //被代理的接口 指定 实现类 MyService myService = new MyServiceImpl(); LOGGER.info("通过类实例调用方法:"); myService.print(); myService.save(); System.out.println(); LOGGER.info("=======================创建代理实例newProxyInstance======================="); //创建一个 调用处理器,并设置代理对象 InvocationHandler invocationHandler = new MyInvocationHandler(myService); //创建代理实例 LOGGER.info("通过Proxy.newProxyInstance(interface.class.getClassLoader,interface.class[],handler)创建代理实例。"); MyService proxyInstance = (MyService) Proxy.newProxyInstance(//注意类型转换 MyService.class.getClassLoader(),//接口的class loader new Class[]{MyService.class},//接口的类 invocationHandler);//调用处理器 //通过代理调用方法 LOGGER.info("通过代理调用方法:"); proxyInstance.print(); proxyInstance.save(); System.out.println(); LOGGER.info("=======================获取调用处理器getInvocationHandler======================="); //通过Proxy.getInvocationHandler(proxyInstance)获取指定代理的调用处理器 InvocationHandler invocationHandler1 = Proxy.getInvocationHandler(proxyInstance); LOGGER.info("通过Proxy.getInvocationHandler(proxyInstance)获取指定代理的调用处理器:" + invocationHandler1); LOGGER.info("通过代理Proxy的InvocationHandler成员变量执行方法:"); invocationHandler1.invoke(proxyInstance,MyServiceImpl.class.getDeclaredMethod("save"),null); System.out.println(); LOGGER.info("=======================判断是否代理类isProxyClass======================="); //通过Proxy.isProxyClass(clazz)判断是否是代理类 LOGGER.info("通过Proxy.isProxyClass(clazz)判断是否是代理类 - proxyInstance = " + Proxy.isProxyClass(proxyInstance.getClass())); LOGGER.info("通过Proxy.isProxyClass(clazz)判断是否是代理类 - myService = " + Proxy.isProxyClass(myService.getClass()) + "\n"); LOGGER.info("=======================获取代理类getProxyClass======================="); //通过Proxy.getProxyClass(interface.class.getClassLoader(),interface.class)获取代理类的Class对象 Class proxyClass = Proxy.getProxyClass(MyService.class.getClassLoader(), MyService.class); LOGGER.info("通过Proxy.getProxyClass(interface.class.getClassLoader(),interface.class)获取代理类的Class对象:" + proxyClass); LOGGER.info("-----------------------通过构造方法创建代理实例getConstructor.newInstance-----------------------"); //通过代理的构造器创建代理实例 LOGGER.info("通过proxyClass.getConstructor(InvocationHandler.class).newInstance(invocationHandler)创建代理实例"); MyService proxyInstance1 = (MyService) proxyClass.getConstructor(InvocationHandler.class).newInstance(invocationHandler); proxyInstance1.save(); } }
4.运行结果
2018-03-04 15:15:21 INFO ReflectProxyDemo:103 - 通过类实例调用方法: 2018-03-04 15:15:21 INFO ReflectProxyDemo:38 - MyServiceImpl打印信息... 2018-03-04 15:15:21 INFO ReflectProxyDemo:43 - MyServiceImpl保存数据... 2018-03-04 15:15:21 INFO ReflectProxyDemo:108 - =======================创建代理实例newProxyInstance======================= 2018-03-04 15:15:21 INFO ReflectProxyDemo:112 - 通过Proxy.newProxyInstance(interface.class.getClassLoader,interface.class[],handler)创建代理实例。 2018-03-04 15:15:21 INFO ReflectProxyDemo:118 - 通过代理调用方法: 2018-03-04 15:15:21 INFO ReflectProxyDemo:75 - 调用了MyInvocationHandler.invoke(proxy,method,args)...不需要事务控制... 2018-03-04 15:15:21 INFO ReflectProxyDemo:38 - MyServiceImpl打印信息... 2018-03-04 15:15:21 INFO ReflectProxyDemo:80 - 调用了MyInvocationHandler.invoke(proxy,method,args)...需要事务控制... 2018-03-04 15:15:21 INFO ReflectProxyDemo:81 - ~~~~~~~~~~~~~~~~开启事务~~~~~~~~~~~~~~~~ 2018-03-04 15:15:21 INFO ReflectProxyDemo:43 - MyServiceImpl保存数据... 2018-03-04 15:15:21 INFO ReflectProxyDemo:83 - ~~~~~~~~~~~~~~~~提交或回滚事务(commit/rollback等)~~~~~~~~~~~~~~~~ 2018-03-04 15:15:21 INFO ReflectProxyDemo:123 - =======================获取调用处理器getInvocationHandler======================= 2018-03-04 15:15:21 INFO ReflectProxyDemo:126 - 通过Proxy.getInvocationHandler(proxyInstance)获取指定代理的调用处理器:pers.hanchao.reflect.proxy.ReflectProxyDemo$MyInvocationHandler@2dda6444 2018-03-04 15:15:21 INFO ReflectProxyDemo:127 - 通过代理Proxy的InvocationHandler成员变量执行方法: 2018-03-04 15:15:21 INFO ReflectProxyDemo:80 - 调用了MyInvocationHandler.invoke(proxy,method,args)...需要事务控制... 2018-03-04 15:15:21 INFO ReflectProxyDemo:81 - ~~~~~~~~~~~~~~~~开启事务~~~~~~~~~~~~~~~~ 2018-03-04 15:15:21 INFO ReflectProxyDemo:43 - MyServiceImpl保存数据... 2018-03-04 15:15:21 INFO ReflectProxyDemo:83 - ~~~~~~~~~~~~~~~~提交或回滚事务(commit/rollback等)~~~~~~~~~~~~~~~~ 2018-03-04 15:15:21 INFO ReflectProxyDemo:131 - =======================判断是否代理类isProxyClass======================= 2018-03-04 15:15:21 INFO ReflectProxyDemo:133 - 通过Proxy.isProxyClass(clazz)判断是否是代理类 - proxyInstance = true 2018-03-04 15:15:21 INFO ReflectProxyDemo:134 - 通过Proxy.isProxyClass(clazz)判断是否是代理类 - myService = false 2018-03-04 15:15:21 INFO ReflectProxyDemo:136 - =======================获取代理类getProxyClass======================= 2018-03-04 15:15:21 INFO ReflectProxyDemo:139 - 通过Proxy.getProxyClass(interface.class.getClassLoader(),interface.class)获取代理类的Class对象:class pers.hanchao.reflect.proxy.$Proxy0 2018-03-04 15:15:21 INFO ReflectProxyDemo:140 - -----------------------通过构造方法创建代理实例getConstructor.newInstance----------------------- 2018-03-04 15:15:21 INFO ReflectProxyDemo:142 - 通过proxyClass.getConstructor(InvocationHandler.class).newInstance(invocationHandler)创建代理实例 2018-03-04 15:15:21 INFO ReflectProxyDemo:80 - 调用了MyInvocationHandler.invoke(proxy,method,args)...需要事务控制... 2018-03-04 15:15:21 INFO ReflectProxyDemo:81 - ~~~~~~~~~~~~~~~~开启事务~~~~~~~~~~~~~~~~ 2018-03-04 15:15:21 INFO ReflectProxyDemo:43 - MyServiceImpl保存数据... 2018-03-04 15:15:21 INFO ReflectProxyDemo:83 - ~~~~~~~~~~~~~~~~提交或回滚事务(commit/rollback等)~~~~~~~~~~~~~~~~
5.总结
根据代码实例和运行结果,总结如下:通过Proxy.newProxyInstance(interface.class.getClassLoader,interface.class[],handler)创建代理实例
第一个参数是被代理接口的class loader,作为定义这个代理的类加载器。
第二个参数是被代理接口的数组,作为这个代理类要实现的接口
第三个参数是调用处理器(InvocationHandler)的实现类,所有通过这个代理调用的方法实际上都是调用这个实现类的invoke方法。
注意类型转换。
通过Proxy.getInvocationHandler(proxyInstance)获取指定代理的调用处理器
参数为代理对象
通过InvocationHandler实现类的invoke()方法可以进行方法调用。
通过InvocationHandler实现类的invoke()方法,实现各类应用,如:
数据库连接、
事务管理、
拦截器等等。
通过Proxy.isProxyClass(clazz)判断是否是代理类
通过Proxy.getProxyClass(interface.class.getClassLoader(),interface.class)获取代理类对象
第一个参数是被代理接口的class loader,作为定义这个代理的类加载器。
第二个参数是被代理接口的数组,作为这个代理类要实现的接口
通过proxyClass.getConstructor(InvocationHandler.class).newInstance(invocationHandler)创建代理实例
上面提到的通过Proxy.newProxyInstance(…)创建代理实例实际上就是通过proxyClass.getConstructor创建代理实例的分解。
相关文章推荐
- java 设计模式学习笔记六 proxy代理模式
- java 动态代理学习(Proxy,InvocationHandler)
- 【设计模式】学习笔记17:代理模式之保护代理与Java反射
- Java Proxy 代理学习
- Java反射学习总结三(静态代理)
- java反射--动态代理学习案例代码
- java 之 动态代理学习示例
- JAVA Proxy(代理) 学习
- JAVA学习--反射之动态代理模式
- java学习脚印:反射与动态代理
- Java设计模式(10)代理模式(Proxy模式)
- JAVA反射示例四——结合代理模式的远程方法调用事例
- 15. JAVA 反射机制 Part 2(动态代理、类的生命周期、工厂设计模式) ----- 学习笔记
- Java反射学习总结四(动态代理使用实例和内部原理解析)
- java 动态代理学习(Proxy,InvocationHandler)
- java 动态代理学习(Proxy,InvocationHandler)
- 转载:java 动态代理学习(Proxy,InvocationHandler)
- Java动态代理Proxy学习
- java 设计模式学习笔记六 proxy代理模式
- java 动态代理学习(Proxy,InvocationHandler)