﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-andy-j2ee-随笔分类-S2SH Learning</title><link>http://www.blogjava.net/anduo1989/category/49746.html</link><description>JAVA</description><language>zh-cn</language><lastBuildDate>Fri, 07 Oct 2011 12:07:01 GMT</lastBuildDate><pubDate>Fri, 07 Oct 2011 12:07:01 GMT</pubDate><ttl>60</ttl><item><title>Spring-AOP底层原理-JDK动态代理---转载</title><link>http://www.blogjava.net/anduo1989/archive/2011/10/07/360134.html</link><dc:creator>安多</dc:creator><author>安多</author><pubDate>Fri, 07 Oct 2011 11:29:00 GMT</pubDate><guid>http://www.blogjava.net/anduo1989/archive/2011/10/07/360134.html</guid><wfw:comment>http://www.blogjava.net/anduo1989/comments/360134.html</wfw:comment><comments>http://www.blogjava.net/anduo1989/archive/2011/10/07/360134.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/anduo1989/comments/commentRss/360134.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/anduo1989/services/trackbacks/360134.html</trackback:ping><description><![CDATA[<span class="Apple-style-span" style="font-family: 宋体; line-height: 24px; background-color: #ffffff; "><font size="3" style="color: #444444; word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><span style="word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">原文</span></font></span><span class="Apple-style-span" style="color: #444444; font-family: 宋体; line-height: 24px; background-color: #ffffff; font-size: medium; "><a href="http://blog.zdnet.com.cn/html/90/289390-838716.html">http://blog.zdnet.com.cn/html/90/289390-838716.html</a></span><span class="Apple-style-span" style="font-family: 宋体; line-height: 24px; background-color: #ffffff; "><font size="3" style="color: #444444; word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><span style="word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><strong>JDK动态代理</strong></span><br style="word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />&nbsp; &nbsp;</font></span><span class="Apple-style-span" style="color: #444444; font-family: 宋体; font-size: 13px; line-height: 24px; background-color: #eeeeee; "><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #0000FF; ">package</span><span style="color: #000000; ">&nbsp;com.baobaotao.proxy;</span></span><span class="Apple-style-span" style="font-family: 宋体; line-height: 24px; background-color: #ffffff; "><font size="2" style="word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><font class="Apple-style-span" color="#444444">&nbsp;在JDK 1.3以后提供了动态代理的技术，允许开发者在运行期创建接口的代理实例。在Sun刚推出动态代理时，还很难想象它有多大的实际用途，现在我们终于发现动态代理是实现AOP的绝好底层技术。</font><br style="word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /><font class="Apple-style-span" color="#444444">&nbsp;&nbsp;&nbsp; JDK的动态代理主要涉及到java.lang.reflect包中的两个类：Proxy和InvocationHandler。其中InvocationHandler是一个接口，可以通过实现该接口定义横切逻辑，在并通过反射机制调用目标类的代码，动态将横切逻辑和业务逻辑编织在一起。</font><br style="word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /><font class="Apple-style-span" color="#444444">&nbsp;&nbsp; 而Proxy为InvocationHandler实现类动态创建一个符合某一接口的代理实例。这样讲一定很抽象，我们马上着手动用Proxy和InvocationHandler这两个魔法戒对上一节中的性能监视代码进行AOP式的改造。</font><br style="word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /><font class="Apple-style-span" color="#444444">&nbsp;&nbsp;&nbsp; 首先，我们从业务类ForumServiceImpl 中删除性能监视的横切代码，使ForumServiceImpl只负责具体的业务逻辑，如所示：</font><br style="word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /><font class="Apple-style-span" color="#444444">代码清单 5 ForumServiceImpl：移除性能监视横切代码</font><br /><font class="Apple-style-span" color="#444444">&nbsp; &nbsp;&nbsp;</font><div style="background-color: #eeeeee; font-size: 13px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><span style="color: #008080; ">&nbsp;2</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;3</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; "></span><span style="color: #0000ff; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; ">class</span><span style="color: #000000; ">&nbsp;ForumServiceImpl&nbsp;</span><span style="color: #0000ff; ">implements</span><span style="color: #000000; ">&nbsp;ForumService&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;4</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;5</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; ">void</span><span style="color: #000000; ">&nbsp;removeTopic(</span><span style="color: #0000ff; ">int</span><span style="color: #000000; ">&nbsp;topicId)&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;6</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#9312;<br /></span><span style="color: #008080; ">&nbsp;7</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">模拟删除Topic记录:</span><span style="color: #000000; ">"</span><span style="color: #000000; ">+</span><span style="color: #000000; ">topicId);<br /></span><span style="color: #008080; ">&nbsp;8</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000ff; ">try</span><span style="color: #000000; ">&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;9</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;Thread.currentThread().sleep(</span><span style="color: #000000; ">20</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">10</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff; ">catch</span><span style="color: #000000; ">&nbsp;(Exception&nbsp;e)&nbsp;{<br /></span><span style="color: #008080; ">11</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; ">throw</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; ">new</span><span style="color: #000000; ">&nbsp;RuntimeException(e);<br /></span><span style="color: #008080; ">12</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">13</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&#9313;<br /></span><span style="color: #008080; ">14</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;}<br /></span><span style="color: #008080; ">15</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; ">void</span><span style="color: #000000; ">&nbsp;removeForum(</span><span style="color: #0000ff; ">int</span><span style="color: #000000; ">&nbsp;forumId)&nbsp;{<br /></span><span style="color: #008080; ">16</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#9312;<br /></span><span style="color: #008080; ">17</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">模拟删除Forum记录:</span><span style="color: #000000; ">"</span><span style="color: #000000; ">+</span><span style="color: #000000; ">forumId);<br /></span><span style="color: #008080; ">18</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000ff; ">try</span><span style="color: #000000; ">&nbsp;{<br /></span><span style="color: #008080; ">19</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;Thread.currentThread().sleep(</span><span style="color: #000000; ">40</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">20</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff; ">catch</span><span style="color: #000000; ">&nbsp;(Exception&nbsp;e)&nbsp;{<br /></span><span style="color: #008080; ">21</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; ">throw</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; ">new</span><span style="color: #000000; ">&nbsp;RuntimeException(e);<br /></span><span style="color: #008080; ">22</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">23</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#9313;<br /></span><span style="color: #008080; ">24</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;}<br /></span><span style="color: #008080; ">25</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">}</span></div><font class="Apple-style-span" color="#444444">&nbsp; &nbsp;&nbsp;</font></font></span><span class="Apple-style-span" style="color: #444444; font-family: 宋体; line-height: 24px; background-color: #ffffff; font-size: small; ">在代码清单 5中的&#9312;和&#9313;处，原来的性能监视代码被移除了，我们只保留了真正的业务逻辑。<br style="word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />&nbsp;&nbsp;&nbsp; 从业务类中移除的横切代码当然还得找到一个寄居之所，InvocationHandler就是横切代码的家园乐土，我们将性能监视的代码安置在PerformaceHandler中，如代码清单 6所示：<br style="word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />代码清单 6 PerformaceHandler</span><span class="Apple-style-span" style="color: #444444; font-family: 宋体; font-size: 13px; line-height: 24px; background-color: #eeeeee; "><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #0000FF; ">package</span><span style="color: #000000; ">&nbsp;com.baobaotao.proxy;</span></span><span class="Apple-style-span" style="font-family: 宋体; line-height: 24px; background-color: #ffffff; "><font size="2" style="word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><br /><font class="Apple-style-span" color="#444444">&nbsp; &nbsp;&nbsp;</font><div style="background-color: #eeeeee; font-size: 13px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><span style="color: #008080; ">&nbsp;2</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; "></span><span style="color: #0000ff; ">import</span><span style="color: #000000; ">&nbsp;java.lang.reflect.InvocationHandler;<br /></span><span style="color: #008080; ">&nbsp;3</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; "></span><span style="color: #0000ff; ">import</span><span style="color: #000000; ">&nbsp;java.lang.reflect.Method;<br /></span><span style="color: #008080; ">&nbsp;4</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;5</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; "></span><span style="color: #0000ff; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; ">class</span><span style="color: #000000; ">&nbsp;PerformaceHandler&nbsp;</span><span style="color: #0000ff; ">implements</span><span style="color: #000000; ">&nbsp;InvocationHandler&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;6</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; ">private</span><span style="color: #000000; ">&nbsp;Object&nbsp;target;<br /></span><span style="color: #008080; ">&nbsp;7</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; ">public</span><span style="color: #000000; ">&nbsp;PerformaceHandler(Object&nbsp;target){</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&#9312;target为目标的业务类</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;8</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000ff; ">this</span><span style="color: #000000; ">.target&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;target;<br /></span><span style="color: #008080; ">&nbsp;9</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;}<br /></span><span style="color: #008080; ">10</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; ">public</span><span style="color: #000000; ">&nbsp;Object&nbsp;invoke(Object&nbsp;proxy,&nbsp;Method&nbsp;method,&nbsp;Object[]&nbsp;args)<br /></span><span style="color: #008080; ">11</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; ">throws</span><span style="color: #000000; ">&nbsp;Throwable&nbsp;{<br /></span><span style="color: #008080; ">12</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;PerformanceMonitor.begin(target.getClass().getName()</span><span style="color: #000000; ">+</span><span style="color: #000000; ">"</span><span style="color: #000000; ">.</span><span style="color: #000000; ">"</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;method.getName());<br /></span><span style="color: #008080; ">13</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;Object&nbsp;bj&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;method.invoke(target,&nbsp;args);</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&#9313;通过反射方法调用目标业务类的业务方法</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">14</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;PerformanceMonitor.end();<br /></span><span style="color: #008080; ">15</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000ff; ">return</span><span style="color: #000000; ">&nbsp;obj;<br /></span><span style="color: #008080; ">16</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;}<br /></span><span style="color: #008080; ">17</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">}</span></div><font class="Apple-style-span" color="#444444">&nbsp; &nbsp;&nbsp;</font><div style="color: #444444; display: inline-block; "></div></font></span><span class="Apple-style-span" style="color: #444444; font-family: 宋体; line-height: 24px; background-color: #ffffff; font-size: small; ">&nbsp;粗体部分的代码为性能监视的横切代码，我们发现，横切代码只出现一次，而不是原来那样星洒各处。大家注意&#9313;处的method.invoke()，该语句通过反射的机制调用目标对象的方法，这样InvocationHandler的invoke(Object proxy, Method method, Object[] args)方法就将横切代码和目标业务类代码编织到一起了，所以我们可以将InvocationHandler看成是业务逻辑和横切逻辑的编织器。下面，我们对这段代码做进一步的说明。<br style="word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />首先，我们实现InvocationHandler接口，该接口定义了一个 invoke(Object proxy, Method method, Object[] args)的方法，proxy是代理实例，一般不会用到；method是代理实例上的方法，通过它可以发起对目标类的反射调用；args是通过代理类传入的方法参数，在反射调用时使用。<br style="word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />&nbsp;&nbsp;&nbsp; 此外，我们在构造函数里通过target传入真实的目标对象，如&#9312;处所示，在接口方法invoke(Object proxy, Method method, Object[] args)里，将目标类实例传给method.invoke()方法，通过反射调用目标类方法，如&#9313;所示。<br style="word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />&nbsp;&nbsp;&nbsp; 下面，我们通过Proxy结合PerformaceHandler创建ForumService接口的代理实例，如代码清单 7所示：<br style="word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />代码清单 7 TestForumService：创建代理实例</span><span class="Apple-style-span" style="color: #444444; font-family: 宋体; font-size: 13px; line-height: 24px; background-color: #eeeeee; "><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #0000FF; ">package</span><span style="color: #000000; ">&nbsp;com.baobaotao.proxy;</span></span><span class="Apple-style-span" style="font-family: 宋体; line-height: 24px; background-color: #ffffff; "><font size="2" style="word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><br /><font class="Apple-style-span" color="#444444">&nbsp; &nbsp;&nbsp;</font><div style="background-color: #eeeeee; font-size: 13px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><span style="color: #008080; ">&nbsp;2</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; "></span><span style="color: #0000ff; ">import</span><span style="color: #000000; ">&nbsp;java.lang.reflect.Proxy;<br /></span><span style="color: #008080; ">&nbsp;3</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; "></span><span style="color: #0000ff; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; ">class</span><span style="color: #000000; ">&nbsp;TestForumService&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;4</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; ">static</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; ">void</span><span style="color: #000000; ">&nbsp;main(String[]&nbsp;args)&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;5</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;ForumService&nbsp;target&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; ">new</span><span style="color: #000000; ">&nbsp;ForumServiceImpl();</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&#9312;目标业务类<br /></span><span style="color: #008080; ">&nbsp;6</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #008000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; ">&#9313;&nbsp;将目标业务类和横切代码编织到一起</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;7</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;PerformaceHandler&nbsp;handler&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; ">new</span><span style="color: #000000; ">&nbsp;PerformaceHandler(target);<br /></span><span style="color: #008080; ">&nbsp;8</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&#9314;为编织了目标业务类逻辑和性能监视横切逻辑的handler创建代理类</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;9</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;ForumService&nbsp;proxy&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(ForumService)&nbsp;Proxy.newProxyInstance(<br /></span><span style="color: #008080; ">10</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">target.getClass().getClassLoader(),<br /></span><span style="color: #008080; ">11</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;target.getClass().getInterfaces(),<br /></span><span style="color: #008080; ">12</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;handler);<br /></span><span style="color: #008080; ">13</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&#9315;&nbsp;操作代理实例</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">14</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;proxy.removeForum(</span><span style="color: #000000; ">10</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">15</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;&nbsp;proxy.removeTopic(</span><span style="color: #000000; ">1012</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">16</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">&nbsp;}<br /></span><span style="color: #008080; ">17</span><font class="Apple-style-span" color="#444444">&nbsp;</font><span style="color: #000000; ">}</span></div><font class="Apple-style-span" color="#444444">&nbsp; &nbsp; &nbsp;</font><div style="color: #444444; display: inline-block; "></div></font></span><span class="Apple-style-span" style="color: #444444; font-family: 宋体; line-height: 24px; background-color: #ffffff; font-size: small; ">上面的代码完成了业务类代码和横切代码编织和接口代理实例生成的工作，其中在&#9313;处，我们将ForumService实例编织为一个包含性能监视逻辑的PerformaceHandler实例，然后在&#9314;处，通过Proxy的静态方法newProxyInstance()为融合了业务类逻辑和性能监视逻辑的handler创建一个ForumService接口的代理实例，该方法的第一个入参为类加载器，第二个入参为创建的代理实例所要实现的一组接口，第三个参数是整合了业务逻辑和横切逻辑的编织器对象。<br style="word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />按照&#9314;处的设置方式，这个代理实例就实现了目标业务类的所有接口，也即ForumServiceImpl的ForumService接口。这样，我们就可以按照调用ForumService接口的实例相同的方式调用代理实例，如&#9315;所示。运行以上的代码，输出以下的信息：<br />&nbsp; &nbsp;&nbsp;<span class="Apple-style-span" style="color: #000000; font-size: 13px; background-color: #eeeeee; ">begin&nbsp;monitor<img src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #000000; ">模拟删除Forum记录:</span><span style="color: #000000; ">10</span><span style="color: #000000; "><br />end&nbsp;monitor<img src="http://www.blogjava.net/Images/dot.gif" alt="" /><br />com.baobaotao.proxy.ForumServiceImpl.removeForum花费47毫秒。<br /><br />begin&nbsp;monitor<img src="http://www.blogjava.net/Images/dot.gif" alt="" /><br />模拟删除Topic记录:</span><span style="color: #000000; ">1012</span><span style="color: #000000; "><br />end&nbsp;monitor<img src="http://www.blogjava.net/Images/dot.gif" alt="" /><br />com.baobaotao.proxy.ForumServiceImpl.removeTopic花费26毫秒。</span></div>&nbsp; &nbsp; &nbsp;&nbsp;<div style="display: inline-block; "></div></span><span class="Apple-style-span" style="color: #444444; font-family: 宋体; line-height: 24px; font-size: small; background-color: #ffffff; ">我们发现，程序的运行效果和直接在业务类中编写性能监视逻辑的效果一致，但是在这里，原来分散的横切逻辑代码已经被我们抽取到PerformaceHandler中。当其它业务类（如UserService、SystemService等）的业务方法也需要使用性能监视时，我们只要按照以上的方式，分别为它们创建代理对象就可以了。下面，我们用时序图描述调用关系，进一步代理实例的本质，如图1所示：<br />&nbsp; &nbsp;&nbsp;<img src="http://www.blogjava.net/images/blogjava_net/anduo1989/071311285.gif" alt="" /><br /><br />&nbsp; &nbsp;&nbsp;<div style="display: inline-block; "></div></span><span class="Apple-style-span" style="color: #444444; font-family: 宋体; line-height: 24px; background-color: #ffffff; font-size: small; ">&nbsp; 图 1代理实例的时序图<br style="word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />&nbsp;&nbsp;&nbsp; 我们在上图中特别使用虚线阴影的方式对通过代理器创建的ForumService实例进行凸显，该实例内部利用PerformaceHandler整合横切逻辑和业务逻辑。调用者调用代理对象的的removeForum()和removeTopic()方法时，上图的内部调用时序清晰地告诉了我们实际上所发生的一切。</span><span class="Apple-style-span" style="color: #444444; font-family: 宋体; line-height: 24px; font-size: small; background-color: #ffffff; "><br /></span><span class="Apple-style-span" style="color: #444444; font-family: 宋体; line-height: 24px; background-color: #ffffff; "><font size="2" style="word-break: break-all; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><br /><br />&nbsp;<br /><br /></font></span><font class="Apple-style-span" color="#444444" face="宋体"><span class="Apple-style-span" style="line-height: 24px; "><strong><br /></strong></span></font><img src ="http://www.blogjava.net/anduo1989/aggbug/360134.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/anduo1989/" target="_blank">安多</a> 2011-10-07 19:29 <a href="http://www.blogjava.net/anduo1989/archive/2011/10/07/360134.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate学习总结002-IdGenerator</title><link>http://www.blogjava.net/anduo1989/archive/2011/10/07/360096.html</link><dc:creator>安多</dc:creator><author>安多</author><pubDate>Fri, 07 Oct 2011 01:27:00 GMT</pubDate><guid>http://www.blogjava.net/anduo1989/archive/2011/10/07/360096.html</guid><wfw:comment>http://www.blogjava.net/anduo1989/comments/360096.html</wfw:comment><comments>http://www.blogjava.net/anduo1989/archive/2011/10/07/360096.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/anduo1989/comments/commentRss/360096.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/anduo1989/services/trackbacks/360096.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; 首先来看一下如何使用JPA标准定义一个Hibernate的POJO对象Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->&nbsp;1&nbsp;package&nbsp;com.andu...&nbsp;&nbsp;<a href='http://www.blogjava.net/anduo1989/archive/2011/10/07/360096.html'>阅读全文</a><img src ="http://www.blogjava.net/anduo1989/aggbug/360096.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/anduo1989/" target="_blank">安多</a> 2011-10-07 09:27 <a href="http://www.blogjava.net/anduo1989/archive/2011/10/07/360096.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate学习总结001-hibernate概述</title><link>http://www.blogjava.net/anduo1989/archive/2011/10/06/360078.html</link><dc:creator>安多</dc:creator><author>安多</author><pubDate>Thu, 06 Oct 2011 13:35:00 GMT</pubDate><guid>http://www.blogjava.net/anduo1989/archive/2011/10/06/360078.html</guid><wfw:comment>http://www.blogjava.net/anduo1989/comments/360078.html</wfw:comment><comments>http://www.blogjava.net/anduo1989/archive/2011/10/06/360078.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/anduo1989/comments/commentRss/360078.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/anduo1989/services/trackbacks/360078.html</trackback:ping><description><![CDATA[<div><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;说到hibernate，英文意思：冬眠。给我印象最深的是孙文琴老师的那本hibernate深入详解分页上的那句话"let you java object hibernate in the relation database"。其实后边学完了再回头看这句话的时候就发现其实这句话说的很形象，它深刻的反映了hibernate在软件开发中的重要作用：ORM（object relation mapping 对象关系映射），那么要学习hibernate首先需要了解的就是ORM。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;所谓ORM的解释，可以从维基百科中查到：<br /><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;对象关系映射</strong>（Object Relational Mapping，简称ORM，或O/RM，或O/R mapping），是一种<a class="mw-redirect" title="程式设计" href="/wiki/%E7%A8%8B%E5%BC%8F%E8%A8%AD%E8%A8%88"><font color="#0645ad">程式设计</font></a>技术，用于实现<a class="mw-redirect" title="面向对象" href="/wiki/%E7%89%A9%E4%BB%B6%E5%B0%8E%E5%90%91"><font color="#0645ad">面向对象</font></a>编程语言里不同<a title="类型系统" href="/wiki/%E9%A1%9E%E5%9E%8B%E7%B3%BB%E7%B5%B1"><font color="#0645ad">类型系统</font></a>的数据之间的转换。从效果上说，它其实是创建了一个可在编程语言里使用的&#8220;虚拟<a title="对象数据库" href="/wiki/%E5%AF%B9%E8%B1%A1%E6%95%B0%E6%8D%AE%E5%BA%93"><font color="#0645ad">对象数据库</font></a>&#8221;。如今已有很多免费和收费的ORM产品，而有些程序员更倾向于创建自己的的ORM工具。 
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;面向对象是从<a class="mw-redirect" title="软件工程" href="/wiki/%E8%BB%9F%E9%AB%94%E5%B7%A5%E7%A8%8B"><font color="#0645ad">软件工程</font></a>基本原则（如耦合、聚合、封装）的基础上发展起来的，而关系数据库则是从<a title="数学" href="/wiki/%E6%95%B0%E5%AD%A6"><font color="#0645ad">数学</font></a>理论发展而来的，两套理论存在显著的区别。为了解决这个不匹配的现象，对象关系映射技术应运而生。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;简单的说：ORM相当于<a class="new" title="中继数据" href="/w/index.php?title=%E4%B8%AD%E7%B9%BC%E8%B3%87%E6%96%99&amp;action=edit&amp;redlink=1"><font color="#ba0000">中继数据</font></a>。具体到产品上，例如下边的<a title="ADO.NET Entity Framework" href="/wiki/ADO.NET_Entity_Framework"><font color="#0645ad">ADO.NET Entity Framework</font></a>。DLINQ中实体类的属性[Table]就算是一种中继数据。</p>
</font><p><font style="background-color: #cce8cf">对象关系映射成功运用在不同的面向对象持久层产品中，如：<a class="new" title="Torque" href="/w/index.php?title=Torque&amp;action=edit&amp;redlink=1"><font color="#ba0000">Torque</font></a>，<a class="new" title="OJB" href="/w/index.php?title=OJB&amp;action=edit&amp;redlink=1"><font color="#ba0000">OJB</font></a>，<a title="Hibernate" href="/wiki/Hibernate"><font color="#0645ad">Hibernate</font></a>，<a title="TopLink" href="/wiki/TopLink"><font color="#0645ad">TopLink</font></a>，<a class="new" title="Castor JDO" href="/w/index.php?title=Castor_JDO&amp;action=edit&amp;redlink=1"><font color="#ba0000">Castor JDO</font></a>，<a class="new" title="TJDO" href="/w/index.php?title=TJDO&amp;action=edit&amp;redlink=1"><font color="#ba0000">TJDO</font></a>，<a title="Active Record" href="/wiki/Active_Record"><font color="#0645ad">Active Record</font></a>，<a title="NHibernate" href="/wiki/NHibernate"><font color="#0645ad">NHibernate</font></a>，<a title="ADO.NET Entity Framework" href="/wiki/ADO.NET_Entity_Framework"><font color="#0645ad">ADO.NET Entity Framework</font></a> 等。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;以上是维基百科中解释。所的很官僚，就是说的我们大家一般的人不太能理解。我个人的理解就是：对我们这些对JDBC常用操作非常厌倦的人来了个封装，然后给我们各种常用的接口，而且让我们感觉不到我们在操纵数据库，而只是在调人家给的接口，这无形中让我们感觉到很舒服，很惬意。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hibernate同样是ORM工具，那么它给我们提供了那些接口呢？让我列举几个：<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Session、负责执行被持久化对象的CRUD操作(CRUD的任务是完成与<a href="http://baike.baidu.com/view/1088.htm" target="_blank"><font color="#136ec2">数据库</font></a>的交流，包含了很多常见的SQL语句。)。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SessionFactory、负责初始化Hibernate。它充当数据存储源的代理，并负责创建Session对象。这里用到了<a href="http://baike.baidu.com/view/1306799.htm" target="_blank"><font color="#136ec2">工厂模式</font></a><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Transaction、&nbsp;负责事务相关的操作。它是可选的，开发人员也可以设计编写自己的底层事务处理代码<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Query、Query和Criteria接口负责执行各种数据库查询。它可以使用HQL语言或SQL语句两种表达方式<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Configuration、负责配置并启动Hibernate，创建SessionFactory对象。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /><br /></font></p></div><img src ="http://www.blogjava.net/anduo1989/aggbug/360078.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/anduo1989/" target="_blank">安多</a> 2011-10-06 21:35 <a href="http://www.blogjava.net/anduo1989/archive/2011/10/06/360078.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>