代理模式之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

新闻名称:代理模式之Java动态代理
文章出自:http://www.shufengxianlan.com/qtweb/news36/367536.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联