代理模式,相信大多数人都非常熟悉,常见的实现方式是通过公共接口的方式,让我们的目标类和代理类实现同一接口,在代理类中调用目标类对象的方法。具体请看我另一个博客中的文章:Java的代理模式(通过公共接口实现)
。通过接口的方式,有个不好的地方,就是对每个目标类都要写一对与之相对应的接口和代理类,如果业务类很多,就是非常繁锁的工作了。
而加入反射机制的代理模式,可实现一个公共的代理类,省去我们不少功夫。Java的
java.lang.reflect包及其子包中提供了Class、Method、Annotation等有用的类。下面,写个方法代理的类
MethodProxy,实现动态地调用对象的方法。
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 方法代理类
* @author rongxinhua
*
*/
|
|
public class MethodProxy {
private Class clazz; //对象所属的类
private Object target; //目标对象
private Method method; //目标方法
private Object[] params; //参数数组
@SuppressWarnings("unchecked")
public MethodProxy(Object target, String methodName, Object ... params) {
rebindTarget(target, methodName, params); //设置目标对象与方法
}
/**
* 重新设置目标对象与方法
* @param target
* @param methodName
* @param params
*/
public void rebindTarget(Object target, String methodName, Object ... params) {
this.target = target;
this.clazz = target.getClass();
rebindMethod(methodName, params); //设置目标方法
}
/**
* 重新设置目标方法
* @param methodName
* @param params
*/
public void rebindMethod(String methodName, Object ...params) {
this.params = params;
int paramLength = params.length;
Class[] paramTypes = new Class[paramLength];
for(int i = 0 ; i < paramLength ; i ++ ) {
paramTypes[i] = params[i].getClass();
}
try {
this.method = clazz.getMethod(methodName, paramTypes);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
/**
* 动态调用已绑定的方法
*/
public void doMethod() {
try {
this.method.invoke(target, params);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
这样就可以实现动态地调用某个对象的某个方法了,写个测试代码如下:
public class Manager {
public void say() {
System.out.println("Nobody say nothing");
}
public void love(String boy, String girl) {
System.out.println(boy + " love " + girl);
}
}
我们通过代理类来调用Manager类中的say()和love()方法,测试代码如下:
Manager man = new Manager(); //目标对象
MethodProxy proxy = new MethodProxy(man, "say"); //方法代理对象
proxy.doMethod(); //调用被代理的方法
proxy.rebindMethod("love", "Tom", "Marry"); //重新绑定方法
proxy.doMethod(); //调用被代理的方法
这样就实现了动态代理调用对象的方法,上面代码输出结果就不贴出来了。如果要设置前置通知和后置通知等功能,也很容易实现,只需在“proxy.doMethod()”代码处的前面和后面设置即行。
扩展应用:我们在上面的MethodProxy类中加入以下方法:
/**
* 获取方法上的注解
* @param anClazz 注解类
* @return
*/
public Annotation getAnnotation(Class anClazz) {
return this.method.getAnnotation(anClazz);
}
这个方法用来读取方法上的注解(Annotation),有什么用呢?我们写一个注解来测试下。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Low {
int boyAge(); //男孩法定的谈恋爱年龄
int girlAge(); //女孩法定的谈恋爱年龄
}
我们要引进Annotation相关的类:
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
我们另外写一个测试用的业务类:
public class LoveManager {
@Low(boyAge=12, girlAge=10)
public void beAbleToLove(Person boy, Person girl) {
System.out.println(boy.getName() + " is able to love " + girl.getName());
}
}
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//getter方法略
}
接写上例中的proxy对象测试代码:
LoveManager loveManager = new LoveManager();
Person boy = new Person("Tom", 13);
Person girl = new Person("Marry", 10);
proxy.rebindTarget(loveManager, "beAbleToLove", boy, girl); //重新绑定对象和方法
Low low = (Low)proxy.getAnnotation(Low.class);
if(boy.getAge() < low.boyAge()) {
System.out.println(boy.getName() + "还不到法定年龄,不能谈恋爱!");
} else if(girl.getAge() < low.girlAge()) {
System.out.println(girl.getName() + "还不到法定年龄,不能谈恋爱!");
} else {
proxy.doMethod();
}
根据boy和girl的年龄大小,会相应地输出下列之一:
Tom还不到法定年龄,不能谈恋爱!
Marry还不到法定年龄,不能谈恋爱!
Tom is able to love Marry
这就实现了,通过Java的反射来读取Annotation的值,并根据Annotation的值,来处理业务数据有效性的判断,或者面向切面动态地注入对象,或者作日志、拦截器等等。这种用法在所多框架中都常常看到,
我们在开发自己的Java组件时,不妨也采用一下吧!
分享到:
相关推荐
在此基础上,本文对SSH框架和jQuery技术在Java-Web开发中的应用进行了探讨。同时,本文结合时代技术发展的特点,对基于SSH框架的Java-Web数据库配置设计方法进行了研究,并对基于jQuery技术的Java-Web功能优化设计方法...
Java源码分析:深入探讨Iterator模式
探讨计算机软件开发的JAVA编程语言应用 (1).pdf
计算机软件开发的Java编程语言应用探讨.pdf
Java多线程并发机制的应用探讨
Java多线程并发机制的应用探讨.pdf
Java事件处理机制教学方法探讨.pdf
资源名称:Java脚本编程:语言框架与模式内容简介:《Sun公司核心技术丛书·Java脚本编程语言、框架与模式》讲解了脚本语言的基本概念和使用方法,概括了Java开发人员可以使用的解决方案,并探讨了在Java应用程序中...
为能和大家能共同探讨"设计模式",我将自己在学习中的心得写下来,只是想帮助更多 人更容易理解GoF 的《设计模式》。由于原著都是以C++为例, 以Java 为例的设计模式 基本又都以图形应用为例,而我们更关心Java 在中间件...
云计算应用服务模式探讨 云计算应用服务模式探讨
Java平台及应用Java技术的安全问题研究,关于这方面的可以一看
垃圾收集GC(Garbage Collection)是Java语言的核心技术之一,之前我们曾专门探讨过Java 7新增的垃圾回收器G1的新特性,但在JVM的内部运行机制上看,Java的垃圾回收原理与机制并未改变。垃圾收集的目的在于清除不再...
2022年Java源码分析:深入探讨Iterator模式Java教程.docx
JAVA的异常处理机制探讨,java日常处理技术与在设计中的应用
“校企融合”人才培养模式下《Java web应用开发》课程改革的探讨
《java设计模式(第2版)》适合各个层次的java开发人员与设计人员阅读,也可以作为学习java与设计模式的参考读物或教材。 目录: 第1章 绪论 1 第2章 接口型模式介绍 8 第3章 适配器(adapter)模式 13 第4章 外观(facade...
本书通过一个完整的Java项目对经典著作Design Patterns一书介绍的23种设计模式进行了深入分析与讲解,实践性强,却又不失对模式本质的探讨。本书创造性地将这些模式分为5大类别,以充分展现各个模式的重要特征,并...
探讨计算机软件开发的Java编程语言应用
探讨计算机软件开发的Java编程语言应用.pdf
计算机软件开发中Java编程语言的应用探讨.pdf