一、代理概念

      动态代理技术使整个java技术中最重要的一个技术,他是学习java框架的家畜,不会动态代理技术,那么再学习Spring这些框架是学不明白的。

   

       动态代理技术就是用来产生一个对象的代理对象的。在开发中为什么需要为一个对象产生代理对象呢?

      例子: 明星都有一个经纪人,其实代理就是这个经纪人,别人想要找刘德华,必须要找其经纪人来商谈。代理不让你直接和明星对话。

 

      代理对象应该就有和目标对象相同的方法。

      首先我们应该明确代理对象的两个概念:

             1、代理对象存在的价值主要用于拦截对真实业务对象的访问。

             2、代理对象应该具有和目标对象(真实业务对象)相同的方法。

 

二、java中的代理

     2.1 “java.lang.reflect.Proxy”类介绍

             现在要生成某一个对象的代理对象,这个代理对象通常也要编写一个类来生成,

             所以首先要编写用于生成代理对象的类。在java中如何用程序去程序生成一个对象的代理对象呢,java在jdk1.5之后提供了一个“java.lang.reflect.Proxy”,t通过“Proxy”类提供的一个  newProxyInstance 方法用来创建一个对象的代理对象,如下所示。

   static  Obeject  newProxyInstance(ClassLoader  loader,Class<?>[] interfaces,invocationHandler h)

    newProxyInstance方法用来返回一个代理对象,这个方法总共有3个参数,ClassLoader loader 用来指明生成代理对象使用哪个类装载器,Class<?>[] 用来指明生成哪个对象的代理对象,通过接口指定,InvocationHandler  h用来指明产生的这个代理对象要做什么事情。所以我们只需要调用newProxyInstance方法就可以得到某一个对象的代理对象了。     

      编写生成代理对象的类

             在java中规定,要想产生一个对象的代理对象,那么这个对象必须要有一个接口,所以我们首先就是要设计这个对象的接口,在接口中定义这个对象所具有的方法(行为)

      

     

 1 //首先定义对象的行为接口
 2 
 3 public  interface  person{
 4     
 5       String  sing(String name);
 6       String  dance(String name);
 7    
 8 }
 9 
10 //定义目标业务对象类
11 
12 public  class   LiuDeHua  implements  Person{
13      
14     public  String sing(String name){
15           System.out.println("刘德华唱"+name+"歌");
16           return  "歌唱完了,谢谢";
17     }
18     public  String sing(String name){
19           System.out.println("刘德华跳"+name+"舞");
20           return  "舞跳完了,谢谢"
21     }
22     
23    
24 }
25 
26 
27 //创建生成代理对象的代理类
28 public  class  LiuDeHuaProxy{
29    
30     //设计一个类变量记住代理类要代理的目标对象
31     private  Person  ldh = new LiuDeHua();
32 
33     /*
34      设计一个方法生成代理对象
35      
36      
37     */
38 
39    public  Person  getProxy(){
40         
41            //使用Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)返回某个对象的代理对象
42          
43              return  (Person)Proxy.newProxyInstance(LiuDeHuaProxy.class.getClassLoader(),ldh.getClass().getInterfaces(),new InvocationHandler(){
44        
45         /*
46        InvocationHandler 接口只定义了一个 invoke方法,因此对于这样的接口,我们不用单独去定义一个类来实现该接口,而是直接使用一个匿名内部类来实现接口,new  InvocationHandler(){}就是针对InvocationHandler接口的匿名实现类
47       在 invoke 方法编码指定返回的代理对象干的工作
48       proxy: 把代理对象自己传递进来
49       method:把代理对象当前调用的方法传递进来
50       args:把 方法参数传递进来
51      当代哦用代理对象的 person.sing("冰雨");或者 person.dance("舞蹈");方法的时候
52       实际上执行的都是invoke 方法里的代码,因此我们可以在invoke方法中使用  method.getName()就可以知道对象调用的是哪个方法
53      
54        */
55        @Override
56        public  Object  invoke(Object proxy,Method method, Object[] args ) throws Throwable{
57         //如果调用的事代理对象的sing方法
58       if(method.getName().equals("sing")){
59       //返回刘德华唱歌,就是代理对象会调用真是目标对象的sing方法去
60      处理用户请求
61          return  method.invoke(ldh,args); 
62        
63      }
64 
65      if(method.getName().equals("dance")){
66           return  method.invoke(ldh,args); 
67        }
68    
69         return  null;
70     }
71     
72  });
73  
74 
75   }
76 
77 }

 

//测试代码

public  class  ProxyTest{

     public static void  main(String[] args){

       LiuDeHuaProxy  proxy  = new  LiuDeHuaProxy();
       //获得代理对象
       Person  p = proxy.getProxy();
      //调用代理对象的sing方法
       String  retValue  = p.sing("冰雨");
       System.out.println(retValue);
        //String  value = p.dance("江南style");
       System.out.println(value);
     }
}

 

  动态代理应用:

         可以编写字符过滤器  

         处理get请求    通过代理模式

 

         

 

     

posted on 2018-01-16 13:54  Leroy_罗先生  阅读(361)  评论(0编辑  收藏  举报