- 浏览: 214981 次
- 性别:
- 来自: 北京
最新评论
-
xupo:
tzg157 写道qinkangwencai 写道别误导大家了 ...
Java多线程编程环境中单例模式的实现 -
xupo:
qinkangwencai 写道别误导大家了行吗?double ...
Java多线程编程环境中单例模式的实现 -
qaddafi2008:
内部静态类的方法貌似是目前最好的解法了!
Java多线程编程环境中单例模式的实现 -
sanshizi:
学习了
Java多线程编程环境中单例模式的实现 -
tzg157:
qinkangwencai 写道别误导大家了行吗?double ...
Java多线程编程环境中单例模式的实现
代理模式,相信大多数人都非常熟悉,常见的实现方式是通过公共接口的方式,让我们的目标类和代理类实现同一接口,在代理类中调用目标类对象的方法。具体请看我另一个博客中的文章: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();
- }
- }
- }
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);
- }
- }
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(); //调用被代理的方法
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);
- }
/** * 获取方法上的注解 * @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(); //女孩法定的谈恋爱年龄
- }
@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;
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方法略
- }
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();
- }
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组件时,不妨也采用一下吧!
原文地址:http://www.iteye.com/topic/629339
发表评论
-
RHEL5 利用 CentOS的yum 安装openssl gc++及Nginx
2011-04-12 16:17 122271.确保RHEL5中已经安装了yum[root@xupo~]# ... -
用URL重写来实现会话管理
2011-04-11 11:02 1327通常,会话管理是通过服务器将 Session ID 作为一个 ... -
JAVA实现与Linux通信(通过SSH协议)
2011-03-24 14:47 5788使用InputStream和OutputStream来获得命令 ... -
花生壳配置
2011-03-18 17:22 1030[edgen@rhel54 ~]$ su - root口令:[ ... -
服务器相关配置备忘
2011-03-11 10:28 1290JDK安装配置 1、下载jd ... -
Hibernate C3P0 Maven 配置
2011-02-10 14:55 3000pom.xml中增加: <depe ... -
用blazeDS实现推技术
2010-11-11 10:37 1118http://blog.csdn.net/yangyawen/ ... -
用 Quartz 进行作业调度
2010-09-06 14:46 940http://www.ibm.com/developerwor ... -
工作流
2010-09-06 14:26 1051jbpm4 :http://sourceforge.net/p ... -
《构建高性能web站点》读书笔记
2010-08-13 20:20 1056《构建高性能web站点》读书笔记 http://book.g ... -
Comet:基于 HTTP 长连接的“服务器推”技术
2010-08-13 20:15 890http://czh19860925.iteye.com/bl ... -
(转)关于大型软件重构的一些想法
2010-04-01 20:51 1142做当前这个项目也快 ... -
关于设计模式中各种工厂的理解
2010-04-01 20:46 1062对于Java的工厂模式,简单工厂、工厂方法、抽象工厂之间的区别 ... -
OpenNMS架构介绍
2010-03-30 10:06 12601一、OpenNMS简介 OpenNMS的开发基于TMN及FC ... -
OpenNMS配置指南
2010-03-30 09:54 3219OpenNMS的配置是一个繁琐的过程,由于网上没有系统介绍如何 ... -
java调用javascript :js引擎rhino
2009-10-30 16:04 9273前段时间,在浏览javaeye论坛,看见有人征集如何在java ... -
扩展 Eclipse 辅助和规范开发流程
2009-10-26 15:12 1484本如果市场上的开发工具不能满足您的需要,而自己开发 IDE 又 ... -
How to access eclipse workspace?
2009-10-26 14:36 1354摘要: 在开发eclipse pluin的时候,某些情况下 ... -
作业调度器的JAVA实现(第一篇)--Job Scheduling in Java
2009-09-07 23:41 2874On some projects, you find you ... -
对象缓存管理器JAVA实现(第一篇)---一个简单的对象缓存器实现方式
2009-09-07 23:31 2268As I wrote in a previous post, ...
相关推荐
在"JAVA反射与代理"这个主题中,我们将深入探讨这两个核心概念。 首先,让我们了解反射的基本用法。当一个类的名称在运行时才被知道,反射可以帮助我们动态地创建对象。例如,我们可以使用`Class.forName()`方法...
在本教程中,我们将深入探讨Java反射机制的核心概念、功能、API以及应用场景。 **3.1 应用场景** 反射机制在Java开发中广泛应用于框架设计,如Spring、Struts、Hibernate和MyBatis。通过读取配置文件(如XML或...
在实现Bean与XML的互转时,DOM4J和Java反射机制协同工作: 1. **XML到Bean**:首先,使用DOM4J解析XML文件,得到Element对象。然后,通过反射获取Bean的Class对象,并利用反射的newInstance()方法创建Bean实例。...
在本篇“java反射机制学习(五):工厂模式”中,我们将探讨如何利用反射与工厂模式结合,提升代码的灵活性和可扩展性。 首先,工厂模式是一种常用的创建型设计模式,它提供了一种创建对象的最佳方式。传统的工厂模式...
在本文中,我们将深入探讨Java反射机制的基本概念、主要API以及实际应用。 1. **基本概念** 反射机制的核心在于`java.lang.Class`类,它是所有类的通用表示,通过`Class`对象我们可以获取到类的完整信息,包括构造...
总的来说,Java反射机制提供了一种在运行时解析和操作类的能力,这对于实现某些高级功能和灵活的编程模式至关重要。理解并掌握反射的使用,可以帮助我们更好地利用Java平台的潜力,并在设计和实现复杂系统时拥有更多...
下面我们将深入探讨Java反射机制的相关知识点。 1. **什么是反射**: Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;...
下面我们将深入探讨Java反射的基本概念、重要方法以及如何在实际应用中使用它。 1. **什么是反射?** 反射是指在运行时,程序可以获取类的信息(如类名、属性、方法等),并动态地创建对象和调用方法。这使得Java...
Java反射机制是Java语言的一项强大功能,允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。它提供了在运行时访问类、接口、字段和方法的能力,即使这些信息在编译时未知。通过Class对象,我们...
在Java编程中,AOP(面向切面编程)是一种强大的设计模式,它允许开发者将关注点分离,将横切关注点(如日志、事务管理)与核心业务逻辑解耦...理解Spring AOP的工作原理和反射机制对于开发高质量的Java应用至关重要。
通过本文的学习,我们深入了解了Java反射机制的基本概念、应用以及其实现细节。同时,我们也探讨了动态代理机制的工作原理及其在实际开发中的应用场景。这些技术都是Java开发者必须掌握的关键技能之一,能够极大地...
Java语言的反射机制是其强大的特性之一,它允许在运行时检查类、接口、字段和方法的信息,并且能够动态地创建对象和调用方法。这一机制对于理解和利用Java的灵活性至关重要,尤其在元编程、框架设计、插件系统以及...
在IBM的文章中,作者深入探讨了Java反射机制的各个方面,为开发者提供了一个全面的理解。这篇文章是Java程序员提升技能、解决实际问题的宝贵资源。 Java反射的核心概念在于它允许程序在运行时获取类的信息,包括...
在深入探讨Java代理机制之前,我们首先需要了解代理模式的基本概念及其应用场景。代理模式是一种结构型设计模式,它为其他对象提供了一种代理以控制对这个对象的访问。在Java中,代理模式通常用于实现AOP(面向切面...
在Java中,有静态代理和动态代理两种方式,动态代理通常基于Java的反射机制实现。 八、适配器模式(Adapter) 适配器模式作为两个不兼容接口之间的桥梁,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作...
本书“JAVA编程模式与范例_高级应用开发”旨在深入探讨Java语言中的设计模式和最佳实践,以帮助开发者构建更高效、可维护和扩展性强的软件系统。下面我们将详细解析其中可能涉及的知识点。 1. **设计模式**: - **...
代理模式广泛应用于AOP(面向切面编程)、日志、权限控制等场景。本教程将深入探讨Java中的动态代理和静态代理。 ### 静态代理 静态代理是代理模式的最基础形式,它通过创建一个实现了与目标对象相同接口的代理类...
在Java编程语言中,面向对象(Object-Oriented Programming,OOP)是核心特性之一,而接口(Interface)和代理模式(Proxy Pattern)是其中重要的概念。本教程将深入探讨这两个概念及其在实际开发中的应用。 接口在...
此外,Java的反射机制为动态绑定和实现单例模式提供了不同的方法。 "java设计模式"这个文件可能包含了关于Java中设计模式的详细讨论,涵盖了各种模式的用途、优缺点以及如何在Java项目中有效地应用它们。你可能还会...
6. **动态代理**: Java反射机制还支持动态代理,通过`java.lang.reflect.Proxy` 类和`java.lang.reflect.InvocationHandler` 接口,可以在运行时创建代理类,实现对目标类的增强或拦截。 实际应用场景包括但不限于...