代理模式之Java动态代理

开发 后端
本篇文章介绍了代理模式之Java动态代理,希望对大家有所帮助。

1. Overview

Java在java.lang.reflect包下,定义了自己的代理。利用这个包下的类,我们可以在运行时动态地创建一个代理类,实现一个或多个接口。并将方法的调用转发到你所指定的类。因为实际代理是在运行时创建的,所以称为:动态代理。

 

 

Proxy:完全由java产生的,而且实现了完整的subject接口。

InvocationHandler:Proxy上的任何方法调用都会被传入此类,InvocationHandler控制对RealSubject的访问。

因为Java已经帮助我们创建了Proxy类,我们需要有办法告诉Proxy类你要做什么,我们不能像以前一样把代码写入到Proxy类中,因为Proxy类不是我们实现的。那么我们应该放在哪里?放在InvocationHandler类中,InvocationHandler类是响应代理的任何调用。我们可以吧InvocationHandler想成是代理收到方法调用后,请求做实际工作的对象。

2. java.lang.reflect.InvocationHandler

被代理实例所实现的一个接口,内部只有一个invoke()方法,签名如下;

Java代码

  1. public Object invoke(Object proxy, Method method, Object[] args)   

 

当代理的方法被调用的时候,代理就会把这个调用转发给InvocationHandler,也就会调用它的invoke()方法。

3. java.lang.reflect.Proxy

提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类,我们经常使用的静态方式是:

Java代码

  1. newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)  

 

4. 示例:

情形:自己可以查看修改姓名性别,但是不能修改rate。他人可以查看姓名,性别以及修改rate,但是不能修改姓名性别。

4.1 定义一个接口:

Java代码

  1. public interface Person {     
  2.          
  3.     String getName();     
  4.          
  5.     String getGender();     
  6.          
  7.     void setName(String name);     
  8.          
  9.     void setGender(String gender);     
  10.          
  11.     void setRate(int rate);     
  12.          
  13.     int getRate();     
  14. }   

 

4.2 定义实现Person接口类

Java代码

  1. public class PersonImpl implements Person {     
  2. String name;     
  3.     
  4. String gender;     
  5.     
  6. String interests;     
  7.     
  8. int rate;     
  9.     
  10. public String getName() {     
  11.     return name;     
  12. }     
  13.     
  14. public void setName(String name) {     
  15.     this.name = name;     
  16. }     
  17.     
  18. public String getGender() {     
  19.     return gender;     
  20. }     
  21.     
  22. public void setGender(String gender) {     
  23.     this.gender = gender;     
  24. }     
  25.     
  26. public String getInterests() {     
  27.     return interests;     
  28. }     
  29.     
  30. public void setInterests(String interests) {     
  31.     this.interests = interests;     
  32. }     
  33.     
  34. public int getRate() {     
  35.     return rate;     
  36. }     
  37.     
  38. public void setRate(int rate) {     
  39.     this.rate = rate;     
  40. }   

 

4.3 定义OwnerInvocationHandler类,表示如果为本人,则可以进行修改查看姓名性别。

Java代码

  1. public class OwnerInvocationHandler implements InvocationHandler{     
  2.          
  3.     private Person personBean;     
  4.          
  5.     public OwnerInvocationHandler(Person personBean){     
  6.         this.personBean = personBean;     
  7.     }     
  8.          
  9.     @Override    
  10.     public Object invoke(Object proxy, Method method, Object[] args)     
  11.             throws IllegalAccessException {     
  12.              
  13.         try {     
  14.             if(method.getName().startsWith("get")){//如果方法名为get,就调用person类内的get相应方法     
  15.     
  16.                 return method.invoke(personBean, args);     
  17.             }else if(method.getName().equals("setRate")){ // 如果方法是setRate,则抛出异常     
  18.                 throw new IllegalAccessException("access deny");     
  19.             }else if(method.getName().startsWith("set")){  //如果为set,就调用person类内的set相应方法     
  20.                 return method.invoke(personBean, args);     
  21.             }else {     
  22.                 System.out.println("non method invoke");     
  23.             }     
  24.         } catch (InvocationTargetException e) {     
  25.             e.printStackTrace();     
  26.         }     
  27.         return null;      
  28.              
  29.     }     
  30.          
  31. }    

 

4.4 定义NonInvocationHandler类,表示如果不为本人,则可以进行查看姓名性别和修改rate。

Java代码

  1. public class NonInvocationHandler implements InvocationHandler{     
  2.     //     
  3.     private Person person;     
  4.          
  5.     public NonInvocationHandler(Person person){     
  6.         this.person = person;     
  7.     }     
  8.     
  9.     @Override    
  10.     public Object invoke(Object proxy, Method method, Object[] args)     
  11.             throws Throwable {     
  12.         if(method.getName().startsWith("setRate")){     
  13.             return method.invoke(person, args);     
  14.         }else if (method.getName().startsWith("get")){     
  15.             return method.invoke(person, args);     
  16.         } else {     
  17.             System.out.println("non method invoke");     
  18.             return null;     
  19.         }     
  20.     }     
  21.          
  22. }   

 

4.5 测试类MyDynamicProxy

Java代码

  1. public class MyDynamicProxy {     
  2.     
  3. public Person getOwnerPersonBeanProxy(Person person){     
  4.     return (Person)Proxy.newProxyInstance(person.getClass().getClassLoader(),      
  5.             person.getClass().getInterfaces(), new OwnerInvocationHandler(person));     
  6. }     
  7.     
  8. public Person getNonPersonBeanProxy(Person person){     
  9.     return (Person)Proxy.newProxyInstance(person.getClass().getClassLoader(),      
  10.             person.getClass().getInterfaces(), new NonInvocationHandler(person));     
  11. }     
  12.     
  13. public static void main(String[] args) {     
  14.     MyDynamicProxy mdp = new MyDynamicProxy();     
  15.     mdp.test();     
  16.          
  17. }     
  18.     
  19. public void test(){     
  20.                 //     
  21.     Person person = getPersonBeanFromDB1();     
  22.     Person personProxy = getOwnerPersonBeanProxy(person);     
  23.     System.out.println(personProxy.getName());      
  24.     try {     
  25.         personProxy.setRate(2);     
  26.     } catch (Exception e) {     
  27.         System.out.println("can not setRate");     
  28.     }     
  29.                  //     
  30.     Person person1 = getPersonBeanFromDB1();     
  31.     Person personProxy2 = getNonPersonBeanProxy(person1);     
  32.     System.out.println(personProxy2.getName());     
  33.     personProxy2.setRate(2);     
  34.     System.out.println(personProxy2.getRate());     
  35. }     
  36.     
  37. private Person getPersonBeanFromDB1(){     
  38.     Person pb = new PersonImpl();     
  39.     pb.setName("remy");     
  40.     pb.setGender("girl");     
  41.     pb.setRate(1);     
  42.     return pb;     
  43. }   

 

输出结果:

Java代码

  1. remy     
  2. can not setRate     
  3. remy     
  4. 2 

【编辑推荐】

  1. Java程序开发中代理技术的使用方法
  2. 浅谈Java中用动态代理类实现记忆功能
  3. 探讨Java代理模式与反射机制的实际应用 
责任编辑:金贺 来源: ITEYE博客
相关推荐

2011-03-23 10:40:51

java代理模式

2017-10-12 14:56:11

2011-11-17 14:32:45

Java静态代理动态代理

2012-02-29 09:41:14

JavaScript

2021-06-29 08:54:23

设计模式代理模式远程代理

2012-01-13 15:59:07

2012-08-28 10:59:26

JavaJava动态代理Proxy

2023-12-06 08:23:44

代理模式设计模式

2010-03-25 08:52:30

PHP设计模式代理模式

2017-05-11 21:30:01

Android动态代理ServiceHook

2015-09-22 11:09:47

Java 8动态代理

2021-07-06 06:39:22

Java静态代理动态代理

2021-09-08 07:18:30

代理模式对象

2023-02-24 07:42:30

Java动态代理

2015-09-28 15:59:00

Java动态代理机制

2022-09-07 08:25:08

代理模式设计模式代码

2015-09-24 08:55:14

Java动态代理扩展

2015-09-24 08:54:36

java动态代理

2020-12-28 07:47:35

动态代理AOP

2022-01-26 00:05:00

AOPRPC远程调用
点赞
收藏

51CTO技术栈公众号