java反射机制在代理模式中的使用
来源:互联网 发布:dd windows iso 编辑:程序博客网 时间:2024/05/16 02:54
代理模式的核心思路就是一个接口有两个子类,一个子类完成核心的业务操作,另一个子类完成与核心业务有关的辅助性操作。
代理模式分为静态代理模式和动态代理模式。
静态代理模式:
- //接口类
- interface Food{
- public void eat();
- }
- //核心业务操作类
- class RealFood implements Food{
- @Override
- public void eat() {
- System.out.println(”马小超在吃饭!”);
- }
- }
- //与核心业务有关的辅助性操作
- class ProxyFood implements Food{
- private Food food;
- public Food bind(Food food){
- this.food = food;
- return this;
- }
- @Override
- public void eat() {
- this.prepare();
- this.food.eat();
- this.after();
- }
- private void prepare(){
- System.out.println(”吃饭钱准备:洗手”);
- }
- private void after(){
- System.out.println(”吃饭后收拾:洗碗”);
- }
- }
- //测试类
- public class StaticProxy {
- public static void main(String[] args){
- Food food = new ProxyFood().bind(new RealFood());
- food.eat();
- }
- }
//接口类interface Food{ public void eat();}//核心业务操作类class RealFood implements Food{ @Override public void eat() { System.out.println("马小超在吃饭!"); }}//与核心业务有关的辅助性操作class ProxyFood implements Food{ private Food food; public Food bind(Food food){ this.food = food; return this; } @Override public void eat() { this.prepare(); this.food.eat(); this.after(); } private void prepare(){ System.out.println("吃饭钱准备:洗手"); } private void after(){ System.out.println("吃饭后收拾:洗碗"); }}//测试类public class StaticProxy { public static void main(String[] args){ Food food = new ProxyFood().bind(new RealFood()); food.eat(); }}输出结果:
- 吃饭钱准备:洗手
- 马小超在吃饭!
- 吃饭后收拾:洗碗
吃饭钱准备:洗手马小超在吃饭!吃饭后收拾:洗碗
如上代码所示,定义一个接口类Food,定义一个实现类RealFood来完成核心业务操作,同时再定义一个代理类ProxyFood来完成与核心业务相关的辅助操作。
在代理类ProxyFood中引入代理对象food,定义辅助操作的方法,在重写的eat()方法中引用辅助操作方法。代码如上面所示。
静态的代理模式都是一个接口两个子类,这样一来就会导致一个类只能为一个接口服务。如果有几十个接口,那项目就别做了,这样的设计有很明显的缺陷。那么怎么样才能解决这个问题了?利用反射就可以解决啦。
动态代理模式:
要实现动态代理,则必须实现反射包中的InvocationHandler接口,该接口中只定义了一个invoke()方法,在代理实例上处理方法调用并返回结果。
- Object invoke(Object proxy,Method method,Object[] args)throws Throwable
Object invoke(Object proxy,Method method,Object[] args)throws Throwable
invoke()方法接受的参数如下:
proxy:需要代理的对象
method:表示真实主体要调用的执行方法
args:调用方法时(上面的method代表的方法)传递的参数
在调用invoke()方法时,所有的真实主体类都需要返回一个代理对象,而这个代理对象由Porxy类中的newProxyInstance方法来完成。
- public static Object newProxyInstance(ClassLoader loader,
- Class<?>[] interfaces,
- InvocationHandler h)
- throws IllegalArgumentException
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
该方法返回一个指定接口的代理实例,这个指定接口可以将方法调用指派到指定的调用处理程序。
newProxyInstance需要的参数如下:loader:定义被代理类的类加载器。
interfaces:被代理类要实现接口列表
h:指派方法调用的调用处理程序,用被代理类的实例创建动态代理类的实例,用于真正调用处理程序
代码如下:
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
- //接口类
- interface DaoI{
- public void doSave();
- public Object getById(String id);
- }
- //DaoI实现类,真实主体类,即被代理类
- class DaoImpl implements DaoI{
- @Override
- public void doSave() {
- System.out.println(”执行保存方法【doSave】”);
- }
- @Override
- public Object getById(String id) {
- System.out.println(”执行根据ID查找对象方法【getById】”);
- return null;
- }
- }
- //InvocationHandler实现类
- class DaoProxy implements InvocationHandler{
- //被代理类的对象
- private Object target;
- //绑定被代理对象
- public Object bind(Object target){
- this.target = target;
- //返回实现了被代理类所实现的所有接口的Object对象,即动态代理,需要强制转型
- return Proxy.newProxyInstance(target.getClass().getClassLoader(),
- target.getClass().getInterfaces(), this);
- }
- //日志记录方法
- private void log(String method){
- System.out.println(”进行日志记录,方法为:” + method);
- }
- //事物提交方法
- private void commit(){
- System.out.println(”事物提交”);
- }
- /**
- * <p>Discription:覆盖InvocationHandler接口中的invoke()方法</p>
- * @param proxy 需要代理的对象
- * @param method 真实主体要调用的执行方法
- * @param args 调用方法时传递的参数
- * @return
- * @throws Throwable
- * @author : lcma
- * @update : 2016年10月9日下午2:46:29
- */
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- //日志记录操作
- this.log(method.getName());
- //使用反射中的invoke()对方法进行动态调用
- Object obj = method.invoke(this.target, args);
- //过滤出以do开头的方法,该方法对数据库进行修改,进行事物提交操作
- if(method.getName().matches(“do[a-zA-Z0-9]+”)){
- this.commit();
- }
- return obj;
- }
- }
- //测试类
- public class AutoProxy {
- public static void main(String[] args){
- //获得代理的实例
- DaoI dao = (DaoI)new DaoProxy().bind(new DaoImpl());
- //调用被代理类中的保存方法
- dao.doSave();
- System.out.println(”————–分割线—————–”);
- //获取被代理类中的获取方法
- dao.getById(”123”);
- }
- }
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;//接口类interface DaoI{ public void doSave(); public Object getById(String id);}//DaoI实现类,真实主体类,即被代理类class DaoImpl implements DaoI{ @Override public void doSave() { System.out.println("执行保存方法【doSave】"); } @Override public Object getById(String id) { System.out.println("执行根据ID查找对象方法【getById】"); return null; }}//InvocationHandler实现类class DaoProxy implements InvocationHandler{ //被代理类的对象 private Object target; //绑定被代理对象 public Object bind(Object target){ this.target = target; //返回实现了被代理类所实现的所有接口的Object对象,即动态代理,需要强制转型 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } //日志记录方法 private void log(String method){ System.out.println("进行日志记录,方法为:" + method); } //事物提交方法 private void commit(){ System.out.println("事物提交"); } /** * <p>Discription:覆盖InvocationHandler接口中的invoke()方法</p> * @param proxy 需要代理的对象 * @param method 真实主体要调用的执行方法 * @param args 调用方法时传递的参数 * @return * @throws Throwable * @author : lcma * @update : 2016年10月9日下午2:46:29 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //日志记录操作 this.log(method.getName()); //使用反射中的invoke()对方法进行动态调用 Object obj = method.invoke(this.target, args); //过滤出以do开头的方法,该方法对数据库进行修改,进行事物提交操作 if(method.getName().matches("do[a-zA-Z0-9]+")){ this.commit(); } return obj; }}//测试类public class AutoProxy { public static void main(String[] args){ //获得代理的实例 DaoI dao = (DaoI)new DaoProxy().bind(new DaoImpl()); //调用被代理类中的保存方法 dao.doSave(); System.out.println("--------------分割线-----------------"); //获取被代理类中的获取方法 dao.getById("123"); }}输出结果:
- 进行日志记录,方法为:doSave
- 执行保存方法【doSave】
- 事物提交
- ————–分割线—————–
- 进行日志记录,方法为:getById
- 执行根据ID查找对象方法【getById】
进行日志记录,方法为:doSave执行保存方法【doSave】事物提交--------------分割线-----------------进行日志记录,方法为:getById执行根据ID查找对象方法【getById】
动态代理模式可以让我们在不改变原来代码结构的情况下,对原来的“真实方法”进行扩展、增强其功能,并且可以达到控制被代理对象的行为。
动态代理模式运用的知识点就是Java的反射机制,对于上面的代码有些地方我也不是很理解,要想彻底搞懂还有很长的路要走。
- Java反射机制在代理模式中的使用
- java反射机制在代理模式中的使用
- 在java web 中使用过滤器+反射机制+代理模式,来改进servlet
- java代理模式与反射机制
- java代理模式与反射机制
- java代理模式与反射机制
- 从代理模式到Java反射机制
- java代理模式与反射机制
- 从代理模式到Java反射机制
- java代理模式与反射机制
- java反射机制中的动态代理
- JAVA中的反射机制和动态代理
- Java反射机制在工厂模式中的应用
- java反射机制在工厂模式中的应用
- 反射机制在代理中的应用(一) 静态代理
- 反射机制在代理中的应用(二) 动态代理
- 反射机制在代理中的应用(三) 动态代理中的反射机制
- java 反射机制、代理
- qt 学习
- JavaScript 模块化开发一瞥
- bzoj 1036
- 洛谷 P1282 多米诺骨牌 (背包dp)
- java 线程实时监控硬盘文件目录的文件操作状态
- java反射机制在代理模式中的使用
- C语言中换行符和回车符的区别
- build.gradle其他配置信息
- BRVAH官方使用指南(持续更新)
- java自学-java开发环境搭建
- lua 安装
- 合并两个有序链表
- UNIX编程专题-服务器进程终止/服务器主机崩溃/服务器主机崩溃后重启/服务器主机关机
- Spring简介