<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Open your thoughts &#187; AOP</title>
	<atom:link href="http://blog.baturu.com/index.php/tag/aop/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.baturu.com</link>
	<description>James Gosling is not on the Java road any more !</description>
	<lastBuildDate>Fri, 20 Aug 2010 02:33:20 +0000</lastBuildDate>
	<language>zh-cn</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
	
<!-- Start Of Script Generated By WP-PostViews Plus -->
<script type='text/javascript' src='http://blog.baturu.com/wp-includes/js/jquery/jquery.js?ver=1.4.2'></script>
<script type="text/javascript">
/* <![CDATA[ */
/* ]]> */
</script>
<!-- End Of Script Generated By WP-PostViews Plus -->
	<item>
		<title>Dynamic Proxy Classes</title>
		<link>http://blog.baturu.com/index.php/2009/02/24/dynamic-proxy-classes.html</link>
		<comments>http://blog.baturu.com/index.php/2009/02/24/dynamic-proxy-classes.html#comments</comments>
		<pubDate>Tue, 24 Feb 2009 14:30:48 +0000</pubDate>
		<dc:creator>javafuns</dc:creator>
				<category><![CDATA[Design Patterns]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[AOP]]></category>

		<guid isPermaLink="false">http://blog.baturu.com/?p=648</guid>
		<description><![CDATA[本文翻译自 Java SE 6 Technotes -《Dynamic Proxy Classes》, 少部分内容取自 Java SE API 中文版. Table Of Contents Introduction Dynamic Proxy API Serialization Examples Introduction 一个动态代理类(dynamic proxy class)是实现了一组在运行期指定的接口的类, 通过已实现接口中的某个接口而对代理类某实例的方法调用将被编码并分派给另一个具有同一接口的对象上(a method invocation through one of the interfaces on an instance of the class will be encoded and dispatched to another object through a uniform interface). 因此, 一个动态代理类可用于为一组接口创建类型安全的代理对象而不需预先(例如使用编译期工具)生成这些代理类. 对一个动态代理类的某个实例进行方法调用会被分派给该实例调用处理器(invocation [...]]]></description>
			<content:encoded><![CDATA[<p>本文翻译自 Java SE 6 Technotes -《<a title="Dynamic Proxy Classes" href="http://java.sun.com/javase/6/docs/technotes/guides/reflection/proxy.html" target="_blank">Dynamic Proxy Classes</a>》, 少部分内容取自 Java SE API 中文版.</p>
<h3>Table Of Contents</h3>
<p style="padding-left: 30px;"><strong> <a href="file:///D:/Source/JDK_1.6.0_docs/technotes/guides/reflection/proxy.html#intro">Introduction</a><br />
<a href="file:///D:/Source/JDK_1.6.0_docs/technotes/guides/reflection/proxy.html#api">Dynamic Proxy API</a><br />
<a href="file:///D:/Source/JDK_1.6.0_docs/technotes/guides/reflection/proxy.html#serial">Serialization</a><br />
<a href="file:///D:/Source/JDK_1.6.0_docs/technotes/guides/reflection/proxy.html#examples">Examples</a> </strong></p>
<h3>Introduction</h3>
<p style="padding-left: 30px;">一个动态代理类(<em>dynamic proxy class</em>)是实现了一组在运行期指定的接口的类, 通过已实现接口中的某个接口而对代理类某实例的方法调用将被编码并分派给另一个具有同一接口的对象上(a method invocation through one of the interfaces on an instance of the class will be encoded and dispatched to another object through a uniform interface). 因此, 一个动态代理类可用于为一组接口创建类型安全的代理对象而不需预先(例如使用编译期工具)生成这些代理类. 对一个动态代理类的某个实例进行方法调用会被分派给该实例调用处理器(<em>invocation handler</em>)中的某一方法, 且这些调用会以一个 <code>java.lang.reflect.Method</code> 对象(标识要调用的这些方法)和一个类型为 <code>Object</code> 的数组(包含方法参数信息)进行编码.</p>
<p style="padding-left: 30px;">对于那些需要提供对(实现接口的)对象的调用进行安全的反射分派(type-safe reflective dispatch of invocations on objects)的应用程序或者库来说, 动态代理类是非常有用的. 例如, 一个应用程序可以使用一个动态代理类去创建一个实现多个任意(继承自<code>java.util.EventListener</code>)事件监听器接口的对象, 以一种统一风格去处理各种各样的不同类型事件, 例如将所有这样的事件记录到一个文件中.</p>
<h3>Dynamic Proxy Class API</h3>
<p>一个动态代理类<em>(dynamic proxy class)</em> (以下简单引用为代理类(<em>proxy class)</em>) 是一个实现了一组在运行期间所指定的接口列表的类.<br />
<span id="more-648"></span> 一个代理接口<em>(proxy interface)</em> 是指由代理类实现了的一个接口.</p>
<p>一个代理实例<em>(proxy instance)</em> 是代理类的一个实例.</p>
<h4 style="padding-left: 30px;">Creating a Proxy Class</h4>
<p>代理类及其实例是通过使用类 <tt><a href="http://java.sun.com/javase/6/docs/api/java/lang/reflect/Proxy.html">java.lang.reflect.Proxy</a></tt> 的静态方法创建的.</p>
<p>给定一个类加载器和一个接口数组,<code> Proxy.getProxyClass</code> 方法将为这个代理类返回 <code>java.lang.Class</code> 对象.  代理类将定义于所指定的类加载器中, 实现所有提供的接口. 如果对于具有相同顺序的接口数组, 在该类加载器中已经定义有一个代理类, 那么这个已有的代理类将会返回; 否则, 将为这些接口动态生成一个代理类并且定义在该类加载器中.</p>
<p>对于可能传递给 <code>Proxy.getProxyClass</code> 的参数有一些限制 :</p>
<ul>
<li>接口数组中的所有 <code>Class</code> 对象必须表示的是接口, 而非类或者原始类型.</li>
<li>接口数组中不能有任何两个元素引用相同 <code>Class</code> 对象.</li>
<li>所有的接口类型对指定的类加载器来说必须是(通过name)可见的. 换句话说, 对于类加载器 <code>cl</code> 和每个接口 <code>i</code>, 下面的表达式必须是 true:
<pre>	Class.forName(i.getName(), false, cl) == i</pre>
</li>
<li>所有 non-public 接口必须位于相同包内; 否则, 对代理类来说它将不可能实现所有接口, 不管该代理类定义于哪个包内.</li>
<li>对于给定接口的任意一组具有相同方法签名的成员方法来说 :
<ul>
<li>如果这些方法中的某些方法返回类型是原始类型或者 void, 那么所有这些方法必须都具有那种相同的返回类型.</li>
<li>Otherwise, one of the methods must have a return type that is assignable to all of the return types of the rest of the methods.</li>
</ul>
</li>
<li>最终得到的(resulting)代理类务必不能超出虚拟机对类所设定的任何限制. 例如, VM 可能限制一个类可实现的接口数最大为65535; 在这种情况下, 接口数组的大小必须不能超出65535.</li>
</ul>
<p>如果违反任何限制, <code>Proxy.getProxyClass</code> 会抛出一个 <code>IllegalArgumentException</code>.  如果接口数组参数或者它的任何元素是 <code>null</code>, 会抛出一个 <code>NullPointerException</code>.</p>
<p>需注意的是所指定的代理接口的顺序是很重要的: 如果两个使用了相同接口组合的代理类请求, 但是这两个接口组合中接口顺序不同, 将会导致两个完全不同的代理类.  代理类由它们的代理接口的顺序来区分, 以便提供对确定性方法调用的编码, 如当代理接口中的两个或多个接口共享具有同样名字和参数签名的方法的情形下; 这个论点在下面的章节  <a href="http://java.sun.com/javase/6/docs/technotes/guides/reflection/proxy.html#methods"><strong>Methods Duplicated in Multiple Proxy Interfaces</strong></a> 有更详细的描述.</p>
<p>因此不需要在每次使用相同类加载器和接口数组去调用<code>Proxy.getProxyClass</code>时都生成一个新代理类, 动态代理类 API 的实现应该保持有已生成代理类的缓存, 以这些代理类所对应的加载器和接口列表为 key. 实现应该注意不要以一种阻碍类加载器和所有代理类在适当时候被垃圾收集的方式去引用类加载器, 接口和代理类.</p>
<h4 style="padding-left: 30px;">Proxy Class Properties</h4>
<p>一个代理类具有如下属性:</p>
<ul>
<li>代理类是公共的、最终的, 而不是抽象的.</li>
<li>未指定代理类的非限定名称。但是，以字符串 <code>"$Proxy"</code> 开头的类名空间应该为代理类保留.</li>
<li>代理类扩展 <code><a href="file:///D:/Source/JDK_1.6.0_docs/api/java/lang/reflect/Proxy.html">java.lang.reflect.Proxy</a></code>.</li>
<li>代理类会按同一顺序准确地实现其创建时指定的接口.</li>
<li>如果代理类实现了非公共接口，那么它将在与该接口相同的包中定义。否则，代理类的包也是未指定的。注意，包密封将不阻止代理类在运行时在特定包中的成功定义，也不会阻止相同类加载器和带有特定签名的包所定义的类.</li>
<li>由于代理类将实现所有在其创建时指定的接口，所以对其 <code>Class</code> 对象调用 <code>getInterfaces</code> 将返回一个包含相同接口列表的数组（按其创建时指定的顺序），对其 <code>Class</code> 对象调用 <code>getMethods</code> 将返回一个包括这些接口中所有方法的 <code>Method</code> 对象的数组，并且调用 <code>getMethod</code> 将会在代理接口中找到期望的一些方法.</li>
<li>如果给 <a href="../../../java/lang/reflect/Proxy.html#isProxyClass(java.lang.Class)"><code>Proxy.isProxyClass</code></a> 方法传递一个代理类（由 <code>Proxy.getProxyClass</code> 返回的类，或由  <code>Proxy.newProxyInstance</code> 返回的对象的类），则该方法返回 true，否则返回 false.  这个方法的可靠性对于使用它去做出安全决定来说是非常重要的, 因此它的实现应当不仅仅只是测试存疑的 (in question) class是否继承自 <code>java.lang.reflect.Proxy</code>.</li>
<li>一个代理类的 <code>java.security.ProtectionDomain</code> 跟由 bootstrap 加载器所加载的系统类的 <code>java.security.ProtectionDomain</code> 是一样的, 例如 <code>java.lang.Object</code>, 因为代理类的代码是由受信任系统代码所生成的.  这个 protection domain 通常被授予 <code>java.security.AllPermission</code>.</li>
</ul>
<h4 style="padding-left: 30px;">Creating a Proxy Instance</h4>
<p>每个代理类都具有一个 public 构造方法, 带有一个参数, 该参数是接口  <code><a href="file:///D:/Source/JDK_1.6.0_docs/api/java/lang/reflect/InvocationHandler.html">InvocationHandler</a></code> 的一个实现.</p>
<p>每个代理类都有一个与之关联的 invocation handler 对象, 也就是传递给该代理类构造方法的那个对象. 可以不必使用 reflection API 去访问公共构造方法, 也可以通过调用 <code>Proxy.newProxyInstance</code> 方法创建一个代理实例, 该方法包含调用 <code>Proxy.getProxyClass</code> 的操作和对含 invocation handler 参数的构造方法的调用(which combines the actions of calling <code>Proxy.getProxyClass</code> with invoking the constructor with an invocation handler). 如果遇到 <code>Proxy.getProxyClass</code> 一样的问题, <code>Proxy.newProxyInstance</code> 也会抛出 <code>IllegalArgumentException</code>.</p>
<h4 style="padding-left: 30px;">Proxy Instance Properties</h4>
<p>一个代理实例有如下属性:</p>
<ul>
<li>对于给定的一个代理实例 <code>proxy</code> 和该代理类 <code>Foo</code> 所实现接口中的一个接口, 如下表达式将返回 true:
<pre>	<code>proxy instanceof Foo</code></pre>
<p>如下强制转换操作将成功 (而不是抛出一个 <code>ClassCastException</code>):</p>
<pre>	<code>(Foo) proxy</code></pre>
</li>
<li>静态的 <code>Proxy.getInvocationHandler</code> 方法会返回作为方法参数而传递给代理实例构造方法的与该代理实例关联的 invocation handler.  如果传递给 <code>Proxy.getInvocationHandler</code> 的对象不是一个代理实例, 那么会抛出一个 <code>IllegalArgumentException</code>.</li>
<li>在一个代理实例上对它所实现接口的方法进行调用将会被编码并分派给 invocation handler 的 <code>invoke</code> 方法, 下面会提到 <code>invoke</code> 方法.<br />
代理实例自己将作为第一个参数传递给 <code>invoke</code>, 该参数类型为 <code>Object</code>.<br />
传递给 <code>invoke</code> 的第二个参数是 <code>java.lang.reflect.Method</code> 实例, 对应于在代理实例上所调用的接口方法.   <code>Method</code> 对象的声明类是声明了该方法的那个接口, 这个接口可能是代理接口的 super 接口.<br />
传递给 <code>invoke</code> 的第三个参数是一个对象数组, 包含在代理实例上进行方法调用时所传递的参数的值.  原始类型参数将会包装进合适的原始包装类的实例中, 例如 <code>java.lang.Integer</code> or <code>java.lang.Boolean</code>.  <code>invoke</code> 方法的实现可自由不受约束地修改这个数组的内容.<br />
<code>invoke</code> 方法的返回值将是对代理实例上方法调用的返回值.  如果接口方法所声明的返回值是一个原始类型, 那么 <code>invoke</code> 的返回值必须是相应原始类型包装类的一个实例; 否则, 它必须是可指派给(可指派这里可看作是&#8221;等价于&#8221;)所声明返回类型的类型(it must be a type assignable to the declared return type). 如果 <code>invoke</code> 返回值是 <code>null</code> 且接口方法的返回类型是原始类型, 那么对代理实例上的方法调用将会抛出一个 <code>NullPointerException</code> . 否则如果 <code>invoke</code> 返回值不兼容于方法所声明的返回类型, 像上面叙述的, 那么该代理实例将抛出一个 <code>ClassCastException</code> .<br />
如果一个异常由 <code>invoke</code> 方法抛出, 它也会被代理实例上的方法调用抛出. 异常类型必须是可指派给(可指派这里可看作是&#8221;等价于&#8221;)接口方法签名中所声明的某个异常类型或者 unchecked 异常 <code>java.lang.RuntimeException</code> 或者 <code>java.lang.Error</code>.  如果 <code>invoke</code> 抛出了一个 checked 异常, 该异常不可指派给(可指派这里可看作是&#8221;等价于&#8221;)接口方法的 <code>throws</code> 句子中所声明的任何异常类型, 那么从代理实例上的方法调用将会抛出一个 <code><a href="http://java.sun.com/javase/6/docs/api/java/lang/reflect/UndeclaredThrowableException.html">UndeclaredThrowableException</a></code> .  <code>UndeclaredThrowableException</code> 会使用由 <code>invoke</code> 方法所抛出的异常进行构建.</li>
<li>在代理实例上对声明于 <code>java.lang.Object</code> 中的 <code>hashCode</code>, <code>equals</code>, or <code>toString</code> 方法的调用将被编码并分派给 invocation handler 的 <code>invoke</code> 方法, 与接口方法调用会被编码并分派的方式是一样的, 上文已有叙述.  传递给 <code>invoke</code> 的 <code>Method</code> 对象的声明类是 java.lang.Object (The declaring class of the <code>Method</code> object passed to <code>invoke</code> will be <code>java.lang.Object</code>).  代理实例的其它继承自 <code>java.lang.Object</code> 的公共方法不会被代理类覆盖(overridden), 因此调用这些方法就像调用 <code>java.lang.Object</code> 实例上的这些方法似的.</li>
</ul>
<h4 style="padding-left: 30px;">Methods Duplicated in Multiple Proxy Interfaces</h4>
<p>当代理类的两个或多个接口包含一个具有相同名称和参数签名的方法时，代理类的接口顺序变得非常重要。在代理实例上调用这种<em>重复方法</em> 时，传递到调用处理程序( invocation handler )的 <code>Method</code> 对象没有必要成为其声明类可以从接口（通过该接口调用代理方法）的引用类型指派的对象。此限制存在的原因是，生成的代理类中的相应方法实现无法确定它通过哪一个接口调用。因此，在代理实例上调用重复方法时，第一个接口中的方法的  <code>Method</code> 对象包含接口的代理类列表中的方法（直接或通过超级接口继承），该对象会传递到调用处理程序的  <code>invoke</code> 方法，无论该方法调用通过哪一种引用类型发生。</p>
<p>如果代理接口包含某一方法，它的名称和参数签名与 <code>java.lang.Object</code> 的  <code>hashCode</code>、<code>equals</code> 或 <code>toString</code> 方法相同，那么在代理实例上调用这样的方法时，传递到调用处理程序的 <code>Method</code> 对象将使  <code>java.lang.Object</code> 成为其声明类。换句话说，<code>java.lang.Object</code> 公共的非 final 方法理论上在所有代理接口之前，用于确定哪一个 <code>Method</code> 对象传递到调用处理程序。</p>
<p>还要注意，当重复方法被指派到调用处理程序时，<code>invoke</code> 方法可能只抛出 checked 异常类型，该异常类型是可以指派给(可指派这里可看作是&#8221;等价于&#8221;或&#8221;存在于&#8221;)所有通过该代理接口进行调用的代理接口方法 <code>throws</code> 声明语句的某一个异常类型。如果 <code>invoke</code> 方法抛出一个 checked 的异常，该异常没有指派给(可指派这里可看作是&#8221;等价于&#8221;或&#8221;存在于&#8221;)任一代理接口（可通过它调用）中的方法所声明的任何一个异常类型，那么该代理实例上的调用将抛出一个 unchecked 的 UndeclaredThrowableException。此限制表示并非所有的经调用传递给 <code>invoke</code> 方法的  <code>Method</code> 对象上的 <code>getExceptionTypes</code> 方法所返回的异常类型都可以由  <code>invoke</code> 方法成功抛出。</p>
<h3>Serialization</h3>
<p>由于 <code>java.lang.reflect.Proxy</code> 实现了 <code>java.io.Serializable</code>, 代理实例可以被序列化, 就如本节描述那样.  如果一个代理实例包含一个 invocation handler, 然而其又没有实现 <code>java.io.Serializable</code>, 那么如果将这样的实例写入一个<code>java.io.ObjectOutputStream</code> 中将抛出一个 <code>java.io.NotSerializableException</code> . 需注意的是对于代理类来说, 实现 <code>java.io.Externalizable</code> 与序列化时实现 <code>java.io.Serializable</code> 具有同样的效果:  <code>Externalizable</code> 接口的 <code>writeExternal</code> 和 <code>readExternal</code> 方法永远都不会在代理实例(或者 invocation handler)上被调用作为其序列化过程的一部分.  正如所有 <code>Class</code> 对象一样, 用于一个代理类的 <code>Class</code> 对象总是可序列化的.</p>
<p>一个代理类没有可序列化字段, 其 <code>serialVersionUID</code> 为 <code>0L</code>. 换句话说, 当一个代理类的 <code>Class</code> 对象被传递给 <code>java.io.ObjectStreamClass</code> 的静态 <code>lookup</code> 方法时, 返回的 <code>ObjectStreamClass</code> 实例将具有如下属性:</p>
<ul>
<li>调用它的 <code>getSerialVersionUID</code> 方法将返回 <code>0L</code>.</li>
<li>调用它的 <code>getFields</code> 方法将返回一个长度为0的数组.</li>
<li>调用它的 <code>getField</code> 方法(任何字符串参数)将返回 <code>null</code>.</li>
</ul>
<p>对象序列化的流协议支持一种类型代码叫做 <code>TC_PROXYCLASSDESC</code>, 这是流格式语法的一个结束信号(terminal symbol); 它的类型和值由 <code>java.io.ObjectStreamConstants</code> 接口的如下常量字段定义:</p>
<pre>    final static byte TC_PROXYCLASSDESC = (byte)0x7D;</pre>
<p>The grammar also includes the following two rules, the first being an alternate expansion of the original <code>newClassDesc</code> rule:</p>
<p><code>newClassDesc</code>:<br />
<code>TC_PROXYCLASSDESC</code> <code>newHandle</code> <code>proxyClassDescInfo</code></p>
<p><code>proxyClassDescInfo</code>:<br />
<code>(int)&lt;count&gt;</code> <code>proxyInterfaceName[count]</code> <code>classAnnotation</code> <code>superClassDesc</code></p>
<p><code>proxyInterfaceName</code>:<br />
<code>(utf)</code></p>
<p>当一个 <code>ObjectOutputStream</code> 序列化一个代理类的类描述符时, 就如由传递该代理类的 <code>Class</code> 对象给 <code>Proxy.isProxyClass</code> 方法所确定的那样, 它使用 <code>TC_PROXYCLASSDESC</code> 类型代码而不是 <code>TC_CLASSDESC</code>, 遵照以上所述规则.  在 proxyClassDescInfo 的扩展中, <em>proxyInterfaceName</em> 项的先后次序是该代理类所实现的所有接口的名字, 按照调用 <code>Class</code> 对象的 <code>getInterfaces</code> 方法时所返回的顺序. <em>classAnnotation</em> and <em>superClassDesc</em> 具有它们在 <em>classDescInfo</em> 规则中一样的含义. 对于代理类, <em>superClassDesc</em> 是它的 super 类 - <code>java.lang.reflect.Proxy - 的类描述符; including this descriptor allows for the evolution of the serialized representation of the class <code>Proxy</code> for proxy instances.</code></p>
<p>对于非代理类, <code>ObjectOutputStream</code> 调用它的 protected <code>annotateClass</code> 方法以允许子类将自己的数据写入一个特定类的流中.  对于代理类, 就不是调用 <code>annotateClass</code>, 而是调用 <code>java.io.ObjectOutputStream</code> 中的如下方法, 并传递该方法 <code>Class</code> 对象:</p>
<pre>    protected void annotateProxyClass(Class cl) throws IOException;</pre>
<p>在 <code>ObjectOutputStream</code> 里, <code>annotateProxyClass</code> 的默认实现没做任何事情.</p>
<p>当一个 <code>ObjectInputStream</code> 遇到类型码 <code>TC_PROXYCLASSDESC</code>, 它会从流中为代理类反序列化类描述符, 格式如上文所述. 不会为该类描述符调用它的 <code>resolveClass</code> 方法解析 <code>Class</code> 对象, 而是调用<code>java.io.ObjectInputStream</code> 的如下方法:</p>
<pre>    protected Class resolveProxyClass(String[] interfaces)
	throws IOException, ClassNotFoundException;</pre>
<p>在代理类描述符中被反序列化的这组接口名称会作为 <code>interfaces</code> 参数被传递给 <code>resolveProxyClass</code>.</p>
<p><code>ObjectInputStream</code> 的 <code>resolveProxyClass</code> 的默认实现返回调用 <code>Proxy.getProxyClass</code> 并传递一组 <code>Class</code> 对象作为 <code>interfaces</code> 参数的结果. 用于每个名为 <code>i</code> 的接口的 <code>Class</code> 对象就是调用如下方法所返回的结果</p>
<pre>	Class.forName(i, false, loader)</pre>
<p>这里, <code>loader</code> 是位于执行栈顶部的第一个非空类加载器, 或者当栈中没有非空类加载器时为 <code>null</code>.  这是 <code>resolveClass</code> 方法默认行为中相同的类加载器选择. <code>loader</code> 的值也是传递给 <code>Proxy.getProxyClass</code> 的类加载器. 如果 <code>Proxy.getProxyClass</code> 抛出 <code>IllegalArgumentException</code>, <code>resolveClass</code> 也将抛出 <code>ClassNotFoundException</code> 包含有 <code>IllegalArgumentException</code>. 因为代理类永远不会有它自己的序列化字段, 在代理实例的流描述中, classdata[] 完全由用于它的 super 类 &#8211; java.lang.reflect.Proxy &#8211; 的实例数据组成.  <code>Proxy</code> 有一个序列化字段, <code>h</code>, 包含用于该代理实例的 invocation handler.</p>
<h2>Examples</h2>
<p>这是一个简单的例子, 在(实现了随意的一组接口)对象上的方法调用之前或之后会打印一条消息:</p>
<pre name="code" class="java">public interface Foo {
    Object bar(Object obj) throws BazException;
}</pre>
<p>-</p>
<pre name="code" class="java">public class FooImpl implements Foo {
    Object bar(Object obj) throws BazException {
        // ...
    }
}</pre>
<p>-</p>
<pre name="code" class="java">public class DebugProxy implements java.lang.reflect.InvocationHandler {

    private Object obj;

    public static Object newInstance(Object obj) {
	return java.lang.reflect.Proxy.newProxyInstance(
	    obj.getClass().getClassLoader(),
	    obj.getClass().getInterfaces(),
	    new DebugProxy(obj));
    }

    private DebugProxy(Object obj) {
	this.obj = obj;
    }

    public Object invoke(Object proxy, Method m, Object[] args)
	throws Throwable
    {
        Object result;
	try {
	    System.out.println("before method " + m.getName());
	    result = m.invoke(obj, args);
        } catch (InvocationTargetException e) {
	    throw e.getTargetException();
        } catch (Exception e) {
	    throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
	} finally {
	    System.out.println("after method " + m.getName());
	}
	return result;
    }
}</pre>
<p>为 <code>Foo</code> 接口的实现创建一个 <code>DebugProxy</code> 并调用它的某个方法:</p>
<pre name="code" class="java">
    Foo foo = (Foo) DebugProxy.newInstance(new FooImpl());
    foo.bar(null);</pre>
<p>Here is an example of a utility invocation handler class that provides default proxy behavior for methods inherited from <code>java.lang.Object</code> and implements delegation of certain proxy method invocations to distinct objects depending on the interface of the invoked method:</p>
<pre name="code" class="java">import java.lang.reflect.*;

public class Delegator implements InvocationHandler {

    // preloaded Method objects for the methods in java.lang.Object
    private static Method hashCodeMethod;
    private static Method equalsMethod;
    private static Method toStringMethod;
    static {
	try {
	    hashCodeMethod = Object.class.getMethod("hashCode", null);
	    equalsMethod = Object.class.getMethod("equals", new Class[] { Object.class });
	    toStringMethod = Object.class.getMethod("toString", null);
        } catch (NoSuchMethodException e) {
	    throw new NoSuchMethodError(e.getMessage());
	}
    }

    private Class[] interfaces;
    private Object[] delegates;

    public Delegator(Class[] interfaces, Object[] delegates) {
	this.interfaces = (Class[]) interfaces.clone();
	this.delegates = (Object[]) delegates.clone();
    }

    public Object invoke(Object proxy, Method m, Object[] args)
	throws Throwable
    {
	Class declaringClass = m.getDeclaringClass();

	if (declaringClass == Object.class) {
	    if (m.equals(hashCodeMethod)) {
		return proxyHashCode(proxy);
	    } else if (m.equals(equalsMethod)) {
		return proxyEquals(proxy, args[0]);
	    } else if (m.equals(toStringMethod)) {
		return proxyToString(proxy);
	    } else {
		throw new InternalError("unexpected Object method dispatched: " + m);
	    }
	} else {
	    for (int i = 0; i &lt; interfaces.length; i++) {
		if (declaringClass.isAssignableFrom(interfaces[i])) {
		    try {
			return m.invoke(delegates[i], args);
		    } catch (InvocationTargetException e) {
			throw e.getTargetException();
		    }
		}
	    }

	    return invokeNotDelegated(proxy, m, args);
	}
    }

    protected Object invokeNotDelegated(Object proxy, Method m, Object[] args)
	throws Throwable
    {
	throw new InternalError("unexpected method dispatched: " + m);
    }

    protected Integer proxyHashCode(Object proxy) {
	return new Integer(System.identityHashCode(proxy));
    }

    protected Boolean proxyEquals(Object proxy, Object other) {
	return (proxy == other ? Boolean.TRUE : Boolean.FALSE);
    }

    protected String proxyToString(Object proxy) {
	return proxy.getClass().getName() + '@' +
	    Integer.toHexString(proxy.hashCode());
    }
}</pre>
<p>Subclasses of <code>Delegator</code> can override <code>invokeNotDelegated</code> to implement the behavior of proxy method invocations not to be directly delegated to other objects, and they can override<code>proxyHashCode</code>, <code>proxyEquals</code>, and <code>proxyToString</code> to override the default behavior of the methods the proxy inherits from <code>java.lang.Object</code>.</p>
<p>To construct a <code>Delegator</code> for an implementation of the <code>Foo</code> interface:</p>
<pre name="code" class="java">
    Class[] proxyInterfaces = new Class[] { Foo.class };
    Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
	proxyInterfaces,
	new Delegator(proxyInterfaces, new Object[] { new FooImpl() }));
</pre>
<p>Note that the implementation of the <code>Delegator</code> class given above is intended to be more illustrative than optimized; for example, instead of caching and comparing the <code>Method</code> objects for the<code>hashCode</code>, <code>equals</code>, and <code>toString</code> methods, it could just match them by their string names, because none of those method names are overloaded in <code>java.lang.Object</code>.</p>
<h3  class="related_post_title">Related Posts:</h3><ul class="related_post"><li>2008/03/10 -- <a href="http://blog.baturu.com/index.php/2008/03/10/spring-notes-4-aop.html" title="Spring notes(四) &#8211; AOP">Spring notes(四) &#8211; AOP</a></li><li>2008/03/09 -- <a href="http://blog.baturu.com/index.php/2008/03/09/spring-notes-3-resource.html" title="Spring notes(三) － Resource">Spring notes(三) － Resource</a></li><li>2008/03/09 -- <a href="http://blog.baturu.com/index.php/2008/03/09/spring-notes-2-ioc-container.html" title="Spring notes(二) &#8211; Ioc container">Spring notes(二) &#8211; Ioc container</a></li><li>2008/03/09 -- <a href="http://blog.baturu.com/index.php/2008/03/09/spring-notes-1-overview.html" title="Spring notes(一) &#8211; Overview">Spring notes(一) &#8211; Overview</a></li><li>2010/08/15 -- <a href="http://blog.baturu.com/index.php/2010/08/15/customize_java_packages_generated_by_xmlbeans.html" title="定制 xmlbeans 所生成的 package">定制 xmlbeans 所生成的 package</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.baturu.com/index.php/2009/02/24/dynamic-proxy-classes.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spring notes(四) &#8211; AOP</title>
		<link>http://blog.baturu.com/index.php/2008/03/10/spring-notes-4-aop.html</link>
		<comments>http://blog.baturu.com/index.php/2008/03/10/spring-notes-4-aop.html#comments</comments>
		<pubDate>Mon, 10 Mar 2008 14:08:53 +0000</pubDate>
		<dc:creator>javafuns</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[AOP]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://blog.baturu.com/index.php/archives/66</guid>
		<description><![CDATA[AOP in springframework&#8230; Related Posts:2008/03/09 -- Spring notes(三) － Resource2008/03/09 -- Spring notes(二) &#8211; Ioc container2008/03/09 -- Spring notes(一) &#8211; Overview2009/02/24 -- Dynamic Proxy Classes2008/03/18 -- Spring notes(六) － DAO and ORMapping support]]></description>
			<content:encoded><![CDATA[<p>AOP in springframework&#8230;</p>
<h3  class="related_post_title">Related Posts:</h3><ul class="related_post"><li>2008/03/09 -- <a href="http://blog.baturu.com/index.php/2008/03/09/spring-notes-3-resource.html" title="Spring notes(三) － Resource">Spring notes(三) － Resource</a></li><li>2008/03/09 -- <a href="http://blog.baturu.com/index.php/2008/03/09/spring-notes-2-ioc-container.html" title="Spring notes(二) &#8211; Ioc container">Spring notes(二) &#8211; Ioc container</a></li><li>2008/03/09 -- <a href="http://blog.baturu.com/index.php/2008/03/09/spring-notes-1-overview.html" title="Spring notes(一) &#8211; Overview">Spring notes(一) &#8211; Overview</a></li><li>2009/02/24 -- <a href="http://blog.baturu.com/index.php/2009/02/24/dynamic-proxy-classes.html" title="Dynamic Proxy Classes">Dynamic Proxy Classes</a></li><li>2008/03/18 -- <a href="http://blog.baturu.com/index.php/2008/03/18/spring-notes-6-dao-and-orm-support.html" title="Spring notes(六) － DAO and ORMapping support">Spring notes(六) － DAO and ORMapping support</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.baturu.com/index.php/2008/03/10/spring-notes-4-aop.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spring notes(三) － Resource</title>
		<link>http://blog.baturu.com/index.php/2008/03/09/spring-notes-3-resource.html</link>
		<comments>http://blog.baturu.com/index.php/2008/03/09/spring-notes-3-resource.html#comments</comments>
		<pubDate>Sun, 09 Mar 2008 12:53:55 +0000</pubDate>
		<dc:creator>javafuns</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[AOP]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://blog.baturu.com/index.php/archives/65</guid>
		<description><![CDATA[Resource interface defines the accessor to all various resources, such as file, http resource, ftp resource, class, etc. Built-in implementations: UrlResource ClassPathResource FileSystemResource ServletContextResource InputStreamResource ByteArrayResource Related Posts:2008/03/10 -- Spring notes(四) &#8211; AOP2008/03/09 -- Spring notes(二) &#8211; Ioc container2008/03/09 -- Spring notes(一) &#8211; Overview2009/02/24 -- Dynamic Proxy Classes2008/03/18 -- Spring notes(六) － DAO and ORMapping [...]]]></description>
			<content:encoded><![CDATA[<p>Resource interface defines the accessor to all various resources, such as file, http resource, ftp resource, class, etc.</p>
<p>Built-in implementations:</p>
<ol>
<li>UrlResource</li>
<li>ClassPathResource</li>
<li>FileSystemResource</li>
<li>ServletContextResource</li>
<li>InputStreamResource</li>
<li>ByteArrayResource</li>
</ol>
<h3  class="related_post_title">Related Posts:</h3><ul class="related_post"><li>2008/03/10 -- <a href="http://blog.baturu.com/index.php/2008/03/10/spring-notes-4-aop.html" title="Spring notes(四) &#8211; AOP">Spring notes(四) &#8211; AOP</a></li><li>2008/03/09 -- <a href="http://blog.baturu.com/index.php/2008/03/09/spring-notes-2-ioc-container.html" title="Spring notes(二) &#8211; Ioc container">Spring notes(二) &#8211; Ioc container</a></li><li>2008/03/09 -- <a href="http://blog.baturu.com/index.php/2008/03/09/spring-notes-1-overview.html" title="Spring notes(一) &#8211; Overview">Spring notes(一) &#8211; Overview</a></li><li>2009/02/24 -- <a href="http://blog.baturu.com/index.php/2009/02/24/dynamic-proxy-classes.html" title="Dynamic Proxy Classes">Dynamic Proxy Classes</a></li><li>2008/03/18 -- <a href="http://blog.baturu.com/index.php/2008/03/18/spring-notes-6-dao-and-orm-support.html" title="Spring notes(六) － DAO and ORMapping support">Spring notes(六) － DAO and ORMapping support</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.baturu.com/index.php/2008/03/09/spring-notes-3-resource.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spring notes(二) &#8211; Ioc container</title>
		<link>http://blog.baturu.com/index.php/2008/03/09/spring-notes-2-ioc-container.html</link>
		<comments>http://blog.baturu.com/index.php/2008/03/09/spring-notes-2-ioc-container.html#comments</comments>
		<pubDate>Sun, 09 Mar 2008 12:27:09 +0000</pubDate>
		<dc:creator>javafuns</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Scripts]]></category>
		<category><![CDATA[AOP]]></category>
		<category><![CDATA[IOC]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://blog.baturu.com/index.php/archives/64</guid>
		<description><![CDATA[IOC container, in spring framework is BeanFactory, contains the following functions: controls the lifecycle (creation, init, destroy) controls the scope (like singleton, prototype, request, session, applicationcontext, new in spring) maintains beans&#8217; dependence BeanFactory is the base of the other modules in springframework. Collection type for bean&#8217;s property: list set map props Lazy init for bean:  [...]]]></description>
			<content:encoded><![CDATA[<p>IOC container, in spring framework is BeanFactory, contains the following functions:</p>
<ol>
<li>controls the lifecycle (creation, init, destroy)</li>
<li>controls the scope (like singleton, prototype, request, session, applicationcontext, new in spring)</li>
<li>maintains beans&#8217; dependence</li>
</ol>
<p>BeanFactory is the base of the other modules in springframework.<br />
Collection type for bean&#8217;s property:</p>
<ol>
<li> list</li>
<li>set</li>
<li>map</li>
<li>props</li>
</ol>
<p>Lazy init for bean:  &lt;bean id=&#8221;xxx&#8221; class=&#8221;xxx&#8221; lazy-init=&#8221;true&#8221;&gt;<br />
ApplicationContext: a more useful Ioc container which is BeanFactory&#8217;s subclass,  is much more suitable for programmers to choose in their Enterprise Applications.</p>
<p>including more functions than BeanFactory:</p>
<ol>
<li>MessageResource</li>
<li>Resource loading</li>
<li>Event-broadcasting</li>
<li>Load more than one xml files at one time</li>
</ol>
<h3  class="related_post_title">Related Posts:</h3><ul class="related_post"><li>2008/03/09 -- <a href="http://blog.baturu.com/index.php/2008/03/09/spring-notes-1-overview.html" title="Spring notes(一) &#8211; Overview">Spring notes(一) &#8211; Overview</a></li><li>2008/03/10 -- <a href="http://blog.baturu.com/index.php/2008/03/10/spring-notes-4-aop.html" title="Spring notes(四) &#8211; AOP">Spring notes(四) &#8211; AOP</a></li><li>2008/03/09 -- <a href="http://blog.baturu.com/index.php/2008/03/09/spring-notes-3-resource.html" title="Spring notes(三) － Resource">Spring notes(三) － Resource</a></li><li>2009/09/25 -- <a href="http://blog.baturu.com/index.php/2009/09/25/a_simple_pojo_factory.html" title="一个简单的 POJO factory 实现">一个简单的 POJO factory 实现</a></li><li>2009/02/24 -- <a href="http://blog.baturu.com/index.php/2009/02/24/dynamic-proxy-classes.html" title="Dynamic Proxy Classes">Dynamic Proxy Classes</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.baturu.com/index.php/2008/03/09/spring-notes-2-ioc-container.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spring notes(一) &#8211; Overview</title>
		<link>http://blog.baturu.com/index.php/2008/03/09/spring-notes-1-overview.html</link>
		<comments>http://blog.baturu.com/index.php/2008/03/09/spring-notes-1-overview.html#comments</comments>
		<pubDate>Sun, 09 Mar 2008 02:22:58 +0000</pubDate>
		<dc:creator>javafuns</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[AOP]]></category>
		<category><![CDATA[IOC]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://blog.baturu.com/index.php/archives/62</guid>
		<description><![CDATA[Spring contains following modules: Core: the core(beanfactory) of springframework providing bean management Context: based on BeanFactory, but supports more functions, such as i18n, event-broadcasting, resource-loading, mail, validation, etc. DAO: series of interfaces that you can choose to implement DAOs. ORM: corresponding classes for integrating many ORM utilities to springframework. Web/Web MVC AOP: AOP function you [...]]]></description>
			<content:encoded><![CDATA[<p>Spring contains following modules:</p>
<p><a title="springframework" href="http://blog.baturu.com/wp-content/uploads/2008/03/spring_framework.gif"><img src="http://blog.baturu.com/wp-content/uploads/2008/03/spring_framework.gif" alt="springframework" width="519" height="271" /></a></p>
<ul>
<li>Core: the core(beanfactory) of springframework providing bean management</li>
<li>Context: based on BeanFactory, but supports more functions, such as i18n, event-broadcasting, resource-loading, mail, validation, etc.</li>
<li>DAO: series of interfaces that you can choose to implement DAOs.</li>
<li>ORM: corresponding classes for integrating many ORM utilities to springframework.</li>
<li>Web/Web MVC</li>
<li>AOP: AOP function you can use to log or do transactions.</li>
</ul>
<h3  class="related_post_title">Related Posts:</h3><ul class="related_post"><li>2008/03/09 -- <a href="http://blog.baturu.com/index.php/2008/03/09/spring-notes-2-ioc-container.html" title="Spring notes(二) &#8211; Ioc container">Spring notes(二) &#8211; Ioc container</a></li><li>2008/03/10 -- <a href="http://blog.baturu.com/index.php/2008/03/10/spring-notes-4-aop.html" title="Spring notes(四) &#8211; AOP">Spring notes(四) &#8211; AOP</a></li><li>2008/03/09 -- <a href="http://blog.baturu.com/index.php/2008/03/09/spring-notes-3-resource.html" title="Spring notes(三) － Resource">Spring notes(三) － Resource</a></li><li>2009/09/25 -- <a href="http://blog.baturu.com/index.php/2009/09/25/a_simple_pojo_factory.html" title="一个简单的 POJO factory 实现">一个简单的 POJO factory 实现</a></li><li>2009/02/24 -- <a href="http://blog.baturu.com/index.php/2009/02/24/dynamic-proxy-classes.html" title="Dynamic Proxy Classes">Dynamic Proxy Classes</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.baturu.com/index.php/2008/03/09/spring-notes-1-overview.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
