<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>fantasybei</title>
    <description></description>
    <link>http://fantasybei.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>Java的动态代理机制</title>
        <author>fantasybei</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://fantasybei.javaeye.com">fantasybei</a>&nbsp;
          链接：<a href="http://fantasybei.javaeye.com/blog/198225" style="color:red;">http://fantasybei.javaeye.com/blog/198225</a>&nbsp;
          发表时间: 2008年05月29日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span style="mso-tab-count: 1;"><span style="font-family: Times New Roman;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">第一篇</span><span lang="EN-US"><span style="font-family: Times New Roman;">blog</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">文章，自己是个菜鸟，希望大家能有指出文章中的错误，大家一起进步。</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span lang="EN-US"><span style="font-size: small;"><span style="font-family: Times New Roman;"><img src="../../../topics/download/2dd6b8d7-295f-3172-976c-3b976490ad17" height="500" alt="" style="vertical-align: middle;" width="1000" /></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;">&nbsp;</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span><span style="font-size: medium;"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">上图是代理模式的实现，代理模式主要是用于客户端对真实对象访问之前进行一些控制，例如日志输出，权限控制等，如上图，客户程序只能通过</span><span lang="EN-US"><span style="font-family: Times New Roman;">SubjectProxy</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">来访问</span><span lang="EN-US"><span style="font-family: Times New Roman;">RealSubject</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">，因为代理类和实现类都是实现一个同一个</span><span lang="EN-US"><span style="font-family: Times New Roman;">Subject</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">接口，所以在客户程序看来，他只知道访问的是实现</span><span lang="EN-US"><span style="font-family: Times New Roman;">Subject</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">接口的一个对象，而不管是哪个类的对象，代理类持有被代理对象的引用，在调用方法时，代理对象可以先做一些操作，然后再调用被代理对象的方法。但是这样做的缺点是，一个</span><span lang="EN-US"><span style="font-family: Times New Roman;">Subject</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">就要创建一个代理类，如果</span><span lang="EN-US"><span style="font-family: Times New Roman;">Subject</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">很多，那么就需要为每个</span><span lang="EN-US"><span style="font-family: Times New Roman;">Subject</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">都创建一个代理类，类的数量就会变得很庞大，更重要的是，如果要修改代理功能，比如原来是没有日志输出的，现在要加上日志输出，哪么你需要在每个代理类中添加日志输出的代码，（不过要是权限控制的话，这样的静态代理是不是能实现更细粒度的权限控制？比如我对这个对象的方法可以让所有人访问，而其他一个对象需要有某某权限才能访问。如果在动态代理下，也可以实现对每个对象的细粒度控制，不过那样动态代理类应该会非常庞大了吧</span><span lang="EN-US"><span style="font-family: Times New Roman;">?</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">），</span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><span style="font-size: medium; font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span><span style="font-size: medium;"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp; 在</span><span lang="EN-US"><span style="font-family: Times New Roman;">Java</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">中，还有一种动态代理，他可以解决上面当</span><span lang="EN-US"><span style="font-family: Times New Roman;">Subject</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">很多的时候，每个代理都要生成一个代理类的问题，其主要用到了</span><span lang="EN-US"><span style="font-family: Times New Roman;">java.lang.reflect</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">包下的</span><span lang="EN-US"><span style="font-family: Times New Roman;">Proxy</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">和</span><span lang="EN-US"><span style="font-family: Times New Roman;">InvocationHandler.</span></span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span><span style="font-size: medium;"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">首先我们让一个</span><span lang="EN-US"><span style="font-family: Times New Roman;">Handler</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">类实现</span><span lang="EN-US"><span style="font-family: Times New Roman;">InvocationHandler</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">接口，然后用</span><span lang="EN-US"><span style="font-family: Times New Roman;">Proxy</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">的</span><span lang="EN-US"><span style="font-family: Times New Roman;">Proxy.newProxyInstance(loader, interfaces, h)</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">方法生成一个动态代理对象，其中的三个参数分别为：第一个制类的装载器，第二个是要生成的动态代理类的接口，第三个是实现了</span><span lang="EN-US"><span style="font-family: Times New Roman;">InvocationHandler</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">接口的</span><span lang="EN-US"><span style="font-family: Times New Roman;">Handler</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">类，当调用生成出来的动态代理对象的方法时，他就自动去调用</span><span lang="EN-US"><span style="font-family: Times New Roman;">Handler</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">的</span><span lang="EN-US"><span style="font-family: Times New Roman;">invoke</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">（</span><span lang="EN-US"><span style="font-family: Times New Roman;">InvocationHandler</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">接口要求必须实现</span><span lang="EN-US"><span style="font-family: Times New Roman;">invoke</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">方法）这样就实现了动态代理，即使有很多类，也只要一个代理即可。</span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">&nbsp;</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">&nbsp;</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span><span style="font-size: medium;"><span lang="EN-US"><span style="mso-tab-count: 1;"><span style="font-family: Times New Roman;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">还有两个不太明白的地方就是</span><span lang="EN-US"><span style="font-family: Times New Roman;">invoke</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">方法里的第一个参数，</span><span lang="EN-US"><span style="font-family: Times New Roman;">proxy</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">，应该就是动态代理对象，但是他传到</span><span lang="EN-US"><span style="font-family: Times New Roman;">invoke</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">里面做什么呢？因为在</span><span lang="EN-US"><span style="font-family: Times New Roman;">invoke</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">里再调用他肯定会形成死循环，估计是不是</span><span lang="EN-US"><span style="font-family: Times New Roman;">invoke</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">方法调用的时候要用到</span><span lang="EN-US"><span style="font-family: Times New Roman;">proxy</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">这个对象，但是如果我们是用不到这个对象的，</span><span lang="EN-US"><span style="font-family: Times New Roman;">sun</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">为什么还写在这里呢？不能把它隐藏起来么？还有就是上面我说的细粒度的权限控制问题，如果几个对象的权限访问机制都不一样，哪么就必须得在</span><span lang="EN-US"><span style="font-family: Times New Roman;">invoke</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">中来处理，这样的话，</span><span lang="EN-US"><span style="font-family: Times New Roman;">invoke</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">方法将非常庞大，希望各位高手能指点下哈，本人第一次写</span><span lang="EN-US"><span style="font-family: Times New Roman;">blog</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">，感觉自己的表达能力真的是很差，写这么一篇文章就花了</span><span lang="EN-US"><span style="font-family: Times New Roman;">1</span></span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman';">个多小时，呵呵，以后只能多加练习了。</span></span></span></p>
          <br/>
          <span style="color:red;">
            <a href="http://fantasybei.javaeye.com/blog/198225#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 29 May 2008 13:37:04 +0800</pubDate>
        <link>http://fantasybei.javaeye.com/blog/198225</link>
        <guid>http://fantasybei.javaeye.com/blog/198225</guid>
      </item>
  </channel>
</rss>