首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

研讨Java代理模式与反射机制的实际应用

2012-12-27 
探讨Java代理模式与反射机制的实际应用探讨Java代理模式与反射机制的实际应用(1)Java的代理模式和反射机制

探讨Java代理模式与反射机制的实际应用
探讨Java代理模式与反射机制的实际应用(1)

    Java的代理模式和反射机制,相信Java的开发者们都非常熟悉,文章会通过一个实例,深入探讨代理模式与Java反射机制的实际应用。

    Java提供了一套机制来动态执行方法和构造方法,以及数组操作等,这套机制就叫反射。而代理模式是为其他对象提供一种代理以控制对这个对象的访问,让我们的目标类和代理类实现同一接口,在代理类中调用目标类对象的方法。

    反射机制是如今很多Java流行框架的实现基础,其中包括Spring、Hibernate等。如果我们将反射机制加入到Java的代理模式中,就可以实现一个公共的代理类,省去我们不少功夫。

    1. import?java.lang.reflect.InvocationTargetException;??? ?import?java.lang.reflect.Method;??? ?
    2. /**?? ??*?方法代理类?? ?
    3. ?*?@author?rongxinhua?? ? *?? ?
    4. ?*/?? ?public?class?MethodProxy?{??? ?
    5. ??????? ?????private?Class?clazz;????//对象所属的类??? ?
    6. ????private?Object?target;??//目标对象??? ?????private?Method?method;??//目标方法??? ?
    7. ????private?Object[]?params;????//参数数组??? ???????? ?
    8. ????@SuppressWarnings("unchecked")??? ?????public?MethodProxy(Object?target,?String?methodName,?Object?...?params)?{??? ?
    9. ????????rebindTarget(target,?methodName,?params);???//设置目标对象与方法??? ?????}??? ?
    10. ??????? ?????/**?? ?
    11. ?????*?重新设置目标对象与方法?? ??????*?@param?target?? ?
    12. ?????*?@param?methodName?? ??????*?@param?params?? ?
    13. ?????*/?? ?????public?void?rebindTarget(Object?target,?String?methodName,?Object?...?params)?{??? ?
    14. ????????this.target?=?target;??? ?????????this.clazz?=?target.getClass();??? ?
    15. ????????rebindMethod(methodName,?params);???//设置目标方法??? ?????}??? ?
    16. ??????? ?????/**?? ?
    17. ?????*?重新设置目标方法?? ??????*?@param?methodName?? ?
    18. ?????*?@param?params?? ??????*/?? ?
    19. ????public?void?rebindMethod(String?methodName,?Object?...params)?{??? ?????????this.params?=?params;??? ?
    20. ????????int?paramLength?=?params.length;??? ?????????Class[]?paramTypes?=?new?Class[paramLength];??? ?
    21. ????????for(int?i?=?0?;?i?<?paramLength?;?i?++?)?{??? ?????????????paramTypes[i]?=?params[i].getClass();??? ?
    22. ????????}??? ?????????try?{??? ?
    23. ????????????this.method?=?clazz.getMethod(methodName,?paramTypes);??? ?????????}?catch?(SecurityException?e)?{??? ?
    24. ????????????e.printStackTrace();??? ?????????}?catch?(NoSuchMethodException?e)?{??? ?
    25. ????????????e.printStackTrace();??? ?????????}??? ?
    26. ????}??? ???????? ?
    27. ????/**?? ??????*?动态调用已绑定的方法?? ?
    28. ?????*/?? ?????public?void?doMethod()?{??? ?
    29. ????????try?{??? ?????????????this.method.invoke(target,?params);??? ?
    30. ????????}?catch?(IllegalArgumentException?e)?{??? ?????????????e.printStackTrace();??? ?
    31. ????????}?catch?(IllegalAccessException?e)?{??? ?????????????e.printStackTrace();??? ?
    32. ????????}?catch?(InvocationTargetException?e)?{??? ?????????????e.printStackTrace();??? ?
    33. ????????}??? ?????}??? ?
    34. ?? ?}? ?
    35. ?import?java.lang.reflect.InvocationTargetException; ?
    36. import?java.lang.reflect.Method; ?/** ?
    37. ?*?方法代理类 ??*?@author?rongxinhua ?
    38. ?* ??*/ ?
    39. public?class?MethodProxy?{ ?? ?
    40. ?private?Class?clazz;?//对象所属的类 ??private?Object?target;?//目标对象 ?
    41. ?private?Method?method;?//目标方法 ??private?Object[]?params;?//参数数组 ?
    42. ? ??@SuppressWarnings("unchecked") ?
    43. ?public?MethodProxy(Object?target,?String?methodName,?Object?...?params)?{ ???rebindTarget(target,?methodName,?params);?//设置目标对象与方法 ?
    44. ?} ?? ?
    45. ?/** ???*?重新设置目标对象与方法 ?
    46. ??*?@param?target ???*?@param?methodName ?
    47. ??*?@param?params ???*/ ?
    48. ?public?void?rebindTarget(Object?target,?String?methodName,?Object?...?params)?{ ???this.target?=?target; ?
    49. ??this.clazz?=?target.getClass(); ???rebindMethod(methodName,?params);?//设置目标方法 ?
    50. ?} ?? ?
    51. ?/** ???*?重新设置目标方法 ?
    52. ??*?@param?methodName ???*?@param?params ?
    53. ??*/ ??public?void?rebindMethod(String?methodName,?Object?...params)?{ ?
    54. ??this.params?=?params; ???int?paramLength?=?params.length; ?
    55. ??Class[]?paramTypes?=?new?Class[paramLength]; ???for(int?i?=?0?;?i?<?paramLength?;?i?++?)?{ ?
    56. ???paramTypes[i]?=?params[i].getClass(); ???} ?
    57. ??try?{ ????this.method?=?clazz.getMethod(methodName,?paramTypes); ?
    58. ??}?catch?(SecurityException?e)?{ ????e.printStackTrace(); ?
    59. ??}?catch?(NoSuchMethodException?e)?{ ????e.printStackTrace(); ?
    60. ??} ??} ?
    61. ? ??/** ?
    62. ??*?动态调用已绑定的方法 ???*/ ?
    63. ?public?void?doMethod()?{ ???try?{ ?
    64. ???this.method.invoke(target,?params); ???}?catch?(IllegalArgumentException?e)?{ ?
    65. ???e.printStackTrace(); ???}?catch?(IllegalAccessException?e)?{ ?
    66. ???e.printStackTrace(); ???}?catch?(InvocationTargetException?e)?{ ?
    67. ???e.printStackTrace(); ???} ?
    68. ?} ??
    69. } ??
    70. 这样就可以实现动态地调用某个对象的某个方法了,写个测试代码如下: ??
    71. public?class?Manager?{??? ???????? ?
    72. ????public?void?say()?{??? ?????????System.out.println("Nobody?say?nothing");??? ?
    73. ????}??? ???????? ?
    74. ????public?void?love(String?boy,?String?girl)?{??? ?????????System.out.println(boy?+?"?love?"?+?girl);??? ?
    75. ????}??? ???????? ?
    76. }? ??
    77. public?class?Manager?{ ?? ?
    78. ?public?void?say()?{ ???System.out.println("Nobody?say?nothing"); ?
    79. ?} ?? ?
    80. ?public?void?love(String?boy,?String?girl)?{ ???System.out.println(boy?+?"?love?"?+?girl); ?
    81. ?} ?? ?
    82. }?

    我们通过代理类来调用Manager类中的say()和love()方法,测试代码如下:

    1. Manager?man?=?new?Manager();????//目标对象??? ?MethodProxy?proxy?=?new?MethodProxy(man,?"say");????//方法代理对象??? ?
    2. proxy.doMethod();???//调用被代理的方法??? ?proxy.rebindMethod("love",?"Tom",?"Marry");?//重新绑定方法??? ?
    3. proxy.doMethod();???//调用被代理的方法? ??
    4. Manager?man?=?new?Manager();?//目标对象 ?MethodProxy?proxy?=?new?MethodProxy(man,?"say");?//方法代理对象 ?
    5. proxy.doMethod();?//调用被代理的方法 ?proxy.rebindMethod("love",?"Tom",?"Marry");?//重新绑定方法 ?
    6. proxy.doMethod();?//调用被代理的方法?
    探讨Java代理模式与反射机制的实际应用(2)
      Java的代理模式和反射机制,相信Java的开发者们都非常熟悉,文章会通过一个实例,深入探讨代理模式与Java反射机制的实际应用。

      这样就实现了动态代理调用对象的方法,上面代码输出结果就不贴出来了。如果要设置前置通知和后置通知等功能,也很容易实现,只需在“proxy.doMethod()”代码处的前面和后面设置即行。扩展应用:我们在上面的MethodProxy类中加入以下方法:

      1. /**?? ??*?获取方法上的注解?? ?
      2. ?*?@param?anClazz?注解类?? ??*?@return?? ?
      3. ?*/?? ?public?Annotation?getAnnotation(Class?anClazz)?{??? ?
      4. ????return?this.method.getAnnotation(anClazz);??? ?}? ?
      5. ??/** ?
      6. ??*?获取方法上的注解 ???*?@param?anClazz?注解类 ?
      7. ??*?@return ???*/ ?
      8. ?public?Annotation?getAnnotation(Class?anClazz)?{ ???return?this.method.getAnnotation(anClazz); ?
      9. ?}?

      这个方法用来读取方法上的注解(Annotation),有什么用呢?我们写一个注解来测试下。?

      1. @Retention(RetentionPolicy.RUNTIME)??? ?@Target(ElementType.METHOD)??? ?
      2. @interface?Low?{??? ?????int?boyAge();???? ?
      3. ????int?girlAge();????? ?}? ?
      4. ?@Retention(RetentionPolicy.RUNTIME) ?
      5. @Target(ElementType.METHOD) ?@interface?Low?{ ?
      6. ?int?boyAge();? ??int?girlAge();? ?
      7. }?

      我们要引进Annotation相关的类:?

      1. import?java.lang.annotation.Annotation;??? ?import?java.lang.annotation.ElementType;??? ?
      2. import?java.lang.annotation.Retention;??? ?import?java.lang.annotation.RetentionPolicy;??? ?
      3. import?java.lang.annotation.Target;? ??
      4. import?java.lang.annotation.Annotation; ?import?java.lang.annotation.ElementType; ?
      5. import?java.lang.annotation.Retention; ?import?java.lang.annotation.RetentionPolicy; ?
      6. import?java.lang.annotation.Target;?

      我们另外写一个测试用的业务类:?

      1. public?class?LoveManager?{??? ???????? ?
      2. ????@Low(boyAge=12,?girlAge=10)??? ?????public?void?beAbleToLove(Person?boy,?Person?girl)?{??? ?
      3. ????????System.out.println(boy.getName()?+?"?is?able?to?love?"?+?girl.getName());??? ?????}??? ?
      4. ??????? ?}??? ?
      5. ?? ?public?class?Person?{??? ?
      6. ????private?String?name;??? ?????private?int?age;??? ?
      7. ????public?Person(String?name,?int?age)?{??? ?????????this.name?=?name;??? ?
      8. ????????this.age?=?age;??? ?????}??? ?
      9. ????//getter方法略??? ?}? ?
      10. ?public?class?LoveManager?{ ?
      11. ? ??@Low(boyAge=12,?girlAge=10) ?
      12. ?public?void?beAbleToLove(Person?boy,?Person?girl)?{ ???System.out.println(boy.getName()?+?"?is?able?to?love?"?+?girl.getName()); ?
      13. ?} ?? ?
      14. } ??
      15. public?class?Person?{ ??private?String?name; ?
      16. ?private?int?age; ??public?Person(String?name,?int?age)?{ ?
      17. ??this.name?=?name; ???this.age?=?age; ?
      18. ?} ??//getter方法略 ?
      19. }??

      接写上例中的proxy对象测试代码:?

      1. LoveManager?loveManager?=?new?LoveManager();??? ?Person?boy?=?new?Person("Tom",?13);??? ?
      2. Person?girl?=?new?Person("Marry",?10);??? ?proxy.rebindTarget(loveManager,?"beAbleToLove",?boy,?girl);?//重新绑定对象和方法??? ?
      3. Low?low?=?(Low)proxy.getAnnotation(Low.class);??? ?if(boy.getAge()?<?low.boyAge())?{??? ?
      4. ????System.out.println(boy.getName()?+?"还不到法定年龄,不能谈恋爱!");??? ?}?else?if(girl.getAge()?<?low.girlAge())?{??? ?
      5. ????System.out.println(girl.getName()?+?"还不到法定年龄,不能谈恋爱!");??? ?}?else?{??? ?
      6. ????proxy.doMethod();??? ?}? ?
      7. ???LoveManager?loveManager?=?new?LoveManager(); ?
      8. ??Person?boy?=?new?Person("Tom",?13); ???Person?girl?=?new?Person("Marry",?10); ?
      9. ??proxy.rebindTarget(loveManager,?"beAbleToLove",?boy,?girl);?//重新绑定对象和方法 ???Low?low?=?(Low)proxy.getAnnotation(Low.class); ?
      10. ??if(boy.getAge()?<?low.boyAge())?{ ????System.out.println(boy.getName()?+?"还不到法定年龄,不能谈恋爱!"); ?
      11. ??}?else?if(girl.getAge()?<?low.girlAge())?{ ????System.out.println(girl.getName()?+?"还不到法定年龄,不能谈恋爱!"); ?
      12. ??}?else?{ ????proxy.doMethod(); ?
      13. ??}?

      这就实现了,通过Java的反射机制来读取Annotation的值,并根据Annotation的值,来处理业务数据有效性的判断,或者面向切面动态地注入对象,或者作日志、拦截器等等。这种用法在所多框架中都常常看到, 我们在开发自己的Java组件时,不妨也采用一下吧!

      【编辑推荐】

        Java设计模式之虚拟代理模式关于Java反射机制的一个实例Java实例讲解反射机制ReflectionJAVA反射机制的简单应用

热点排行