Java 代理与动态代理

来源:互联网 发布:云计算专业就业前景 编辑:程序博客网 时间:2024/04/29 04:21


                                                 Java代理&动态代理

 

Java中得代理可以理解为中介,客户端和目标类的中介。

 

 代理: 客户端--(通过)--代理类方法---(调用)---目标方法。

                在代理类调用目标方法前后可以添加一些系统方法。

   特点:代理类和目标类实现相同得接口。为什么?实现了相同接口,

              那么代理类中得方法和目标内得方法相同,方便调用目标方法。

  为什么要使用代理:

         当把一个类做好后(或不知道这个类得具体代码),要为这个类添加新的系统功能

       (如:异常处理,日志,计算方法运行得时间,等等),这个类已经封装好了,不想修改。

         这时就可以创建一个和目标类实现相同接口得代理类,代理类中的方法与目标类中相同,

        代理类中的方法引用目标类的方法。这时就可以在代理类方法,引用目标类方法,

         前后添加系统功能。 达到调用代理类方法就能调用目标类方法,同时还能添加一些系统功能。

如:

接口     interface A             {             void show();             } 目标类:class Bimplements A{    publicvoidshow(){      System.out.println("吃饭");   }}   代理类:class Cimplements A{     publicvoid show(){ long bigTime = System.currentTimeMillis(); //前置系统代码。如: new B().show();       //后置系统代码。如:      long endTime = System.currentTimeMillis();      System.out.println(endTime-bigTime);   }  } 可以在代理类引用目标类,前后添加新的功能。          动态代理:            为什么要有动态代理:           系统中有很多接口,接口下有很多类,如果要为每一个类写代理类,那就非常麻烦。           而java虚拟机可以在运行期动态生成字节码,可以把动态生成的字节码做为代理类。           这就是动态代理,解决了程序员不要直接写每个代理类的问题。想要java虚拟机自动生成动态代理,           需要想java虚拟机中传递两个参数, 一是,目标类的接口。二是:接口的类加载器。 自定义一个collection接口的代理类:        (1) Class  clazzproxy= Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);/*自动生成代理你得创建这个代理得对象。我们只有创建空参得方法,但自动生成代理得类中没有空参得构造方法 用反射得到有惨得构造方法*/                Constructorconstructor=clazzproxy.getConstructor(InvocationHandler.class);//在用constructor.newInstance实例化时,要向里面传递一个InvocationHandler对象。InvocationHandler是接口,不能new对象,所以,定义一个子类实现InvocationHandler接口,将子类对象传给constructor.newInstance(InvocationHandler子类对象)实例化。                class myInvocationHandlerimplementsInvocationHandler{                 @Override                public Object invoke(Objectarg0, Method arg1, Object[] arg2)                      throws Throwable {                   // TODO Auto-generated method stub                   returnnull;                }                               }          //实例化对象                     Constructor  proxy1 =(Constructor)constructor.newInstance(new myInvocationHandler());                (2)  // 自动生成一个动态代理      //1.在内存中得到一个代理字节码,用到proxy类的getproxyclass方法   Class  clazzproxy=  Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);  //自动生成代理你得创建这个代理得对象。我们只有创建空参得方法,但自动生成代理得类中没有空参得构造方法  //用反射得到有惨得构造方法                 Constructorconstructor=clazzproxy.getConstructor(InvocationHandler.class);                               Constructor  proxy2 =(Constructor)constructor.newInstance(new InvocationHandler(){                 @Override                public Object invoke(Objectproxy, Method method,                      Object[]args) throwsThrowable {                   // TODO Auto-generated method stub                   returnnull;                }                               });        (3) //我们用proxy类中newproxyInstance方法,该方法要传递3个参数。  (a):目标接口类加载器(b):目标接口数组(c):InvocationHandler对象。这样直接得到目标类的代理类。  这个方法将创建和实例化何为一体。     Collection  proxy2 =(Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(),                      new Class[] {Collection.class},                      new InvocationHandler(){                      @Override                    public Object invoke(Object proxy, Methodmethod,                      Object[]args) throwsThrowable {                   // TODO Auto-generated method stub                   returnnull;                }                               }                    );   } }   上面的类没有目标,可以在InvocationHandler对象中指定一个目标ArrayList。代码如下:              Collection  proxy2 = (Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(),                      new Class[] {Collection.class},                      new InvocationHandler(){                      @Override                    public Object invoke(Object proxy, Methodmethod,                      Object[]args)                            throws Throwable {                           ArrayList terget =new ArrayList();                          ***************************************                           Object retval= method.invoke(terget,args);//调用目标的方法。                       ********************************                              return retval;                }                               }                    );   } 

}在**部分可以加入系统代码。上面的代码可以将method.invoke()方法和系统方法封装,作为参数传进去。


 

总结:

1.代理类就是一个中介,帮助目标类增加了一些功能,客服端调用代理方法,代理方法调用目标方法,这样代理类就可以在调用目标方法前后增加系统功能。

2.jvm生成的动态代理内部只有一个带InvocationHandler参数的构造方法。

3.代理类从object上继承的方法有很多,其中只对3个方法(hashcode equals tostring)进行开发,其他不会交给代理类实现。

4.静态代理:程序员自己编写而成的代理类源代码。

  动态代理:在运行时jvm利用反射机制自动生成的代理类。


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 想在京东商城开个网店怎么办呢 京东买了东西收货了不想要了怎么办 京东转卖的商品有问题怎么办 如果衣服下架了然后有退货怎么办 想买二手车可没有懂车的人怎么办 买车的时候异地车牌回家怎么办 天猫下单显示下单人数太多券怎么办 英雄联盟进入游戏后无限崩溃怎么办 打开电视显示百度影棒打不开怎么办 家里路由器网速一会快一会慢怎么办 用快看影视下载电影网速太慢怎么办 苹果手机下载东西网速特别慢怎么办 网上买重庆时时彩输了很多钱怎么办 找不到自己在哪个平台借过钱怎么办 九游账号绑定手机之前绑定的怎么办 九游充过钱的游戏忘了游戏名怎么办 百度网盘密码忘了申诉不了怎么办 手机号被别人注册了百度账号怎么办 快手被盗找回时出来重置密码怎么办 魅族账号密码和密保都忘记了怎么办 vivo账号的密保问题忘了怎么办 oppo账号密保问题忘了怎么办 小米手机刷了机忘了账号密码怎么办 忘了小米账号的密码是多少怎么办 千牛账号在手机上被限制登录怎么办 违规的千牛账号被限制登录了怎么办 苹果id和锁屏密码忘记了怎么办 感应门的编程密码忘记了怎么办 交易猫买的号被找回了怎么办 uc上我的小说看不了怎么办 微信零钱忘记密码没有银行卡怎么办 九游平台冻结提不了现怎么办 计算机考试报名登录名忘记了怎么办 云顶扑克提现怎么提不出来怎么办 微信正在下载一直0kb怎么办 守望先锋运行时出现意外错误怎么办 信用卡暂停使用怎么办还能恢复吗 新刷乳胶漆墙面一碰一个坑怎么办 夏天开空调冻着了头疼打喷嚏怎么办 桑蚕丝衣服被沐浴露退了色怎么办 空间被别人知道了密码登录了怎么办