??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲AV成人精品日韩一区,亚洲国产精品无码观看久久,亚洲乱亚洲乱淫久久http://www.tkk7.com/haoxuewu/articles/380633.html陕西BOY陕西BOYTue, 12 Jun 2012 11:02:00 GMThttp://www.tkk7.com/haoxuewu/articles/380633.htmlhttp://www.tkk7.com/haoxuewu/comments/380633.htmlhttp://www.tkk7.com/haoxuewu/articles/380633.html#Feedback0http://www.tkk7.com/haoxuewu/comments/commentRss/380633.htmlhttp://www.tkk7.com/haoxuewu/services/trackbacks/380633.htmlh?h?h?/strong>Q:



下面是一个实际的h报文Q?



①是请求方法,GET和POST是最常见的HTTPҎQ除此以外还包括DELETE、HEAD、OPTIONS、PUT、TRACE。不q,当前的大多数览器只支持GET和POSTQSpring 3.0提供了一个HiddenHttpMethodFilterQ允怽通过“_method”的表单参数指定这些特D的HTTPҎQ实际上q是通过POST提交表单Q。服务端配置了HiddenHttpMethodFilter后,Spring会根据_method参数指定的值模拟出相应的HTTPҎQ这P可以用这些HTTPҎ对处理方法进行映了?

②求对应的URL地址Q它和报文头的Host属性组成完整的hURLQ?#9314;是协议名U及版本受?

④是HTTP的报文头Q报文头包含若干个属性,格式?#8220;属性名:属性?#8221;Q服务端据此获取客户端的信息?

⑤是报文体Q它一个页面表单中的组件值通过param1=value1&param2=value2的键值对形式~码成一个格式化Ԍ它承载多个请求参数的数据。不但报文体可以传递请求参敎ͼhURL也可以通过cM?#8220;/chapter15/user.html? param1=value1&param2=value2”的方式传递请求参数?

对照上面的请求报文,我们把它q一步分解,你可以看Cq更详细的结构图Q?




引用
HttpWatch是强大的|页数据分析工具Q安装后集成到Internet Explorer工具栏中。它不用代理服务器或一些复杂的|络监控工具Q就能抓取请求及响应的完整信息,包括Cookies、消息头、查询参数、响应报文等Q是Web应用开发h员的必备工具?/div>

HTTPh报文头属?/font>

报文头属性是什么东西呢Q我们不妨以一个小故事来说明吧?

引用
快到中午了,张三C惛_食堂吃饭Q于是打电话叫外卖:老板Q我要一份[鱼香肉丝]Q要12Q?0之前l我送过来哦Q我在江湖湖公司研发部,叫张三丰?/div>

q里Q你要[鱼香肉丝]相当于HTTP报文体,?#8220;12Q?0之前送过?#8221;Q你?#8220;张三?#8221;{信息就相当于HTTP的报文头。它们是一些附属信息,帮忙你和饭店老板利完成q次交易?

hHTTP报文和响应HTTP报文都拥有若q个报文兛_性,它们是ؓ协助客户端及服务端交易的一些附属信息?


常见的HTTPh报文头属?/font>

Accept

h报文可通过一?#8220;Accept”报文头属性告诉服务端 客户端接受什么类型的响应?

如下报文头相当于告诉服务端,俺客L能够接受的响应类型仅为纯文本数据啊,你丫别发其它什么图片啊Q视频啊q来Q那h会歇菜的~~~Q?

Java代码 复制代码 收藏代码
  1. Accept:text/plain  


Accept属性的值可以ؓ一个或多个MIMEcd的|关于MIMEcdQ大家请参考:http://en.wikipedia.org/wiki/MIME_type

Cookie

客户端的Cookie是通过q个报文头属性传l服务端的哦Q如下所C:
Java代码 复制代码 收藏代码
  1. Cookie: $Version=1; Skin=new;jsessionid=5F4771183629C9834F8382E23BE13C4C  

服务端是怎么知道客户端的多个h是隶属于一个Session呢?注意到后台的那个jsessionid=5F4771183629C9834F8382E23BE13C4C木有Q原来就是通过HTTPh报文头的Cookie属性的jsessionid的值关联v来的Q(当然也可以通过重写URL的方式将会话ID附带在每个URL的后面哦Q?


Referer

表示q个h是从哪个URLq来的,假如你通过google搜烦Z个商家的q告面Q你对这个广告页面感兴趣Q鼠标一点发送一个请求报文到商家的网站,q个h报文的Referer报文头属性值就是http://www.google.com?
引用

唐僧C西天.
如来问:侬是不是从东土大唐来啊?
唐僧Q厉宻I你咋知道的!
如来Q呵呵,我偷看了你的Referer...


很多貌似奇的网늛控YӞ如著名的 我要?/a>Q,只要在你的网上放上一DJavaScriptQ就可以帮你监控量Q全国访问客L分布情况{报表和图表Q其原理是通过q个Referer及其它一些HTTP报文头工作的?

Cache-Control

对缓存进行控Ӟ如一个请求希望响应返回的内容在客L要被~存一q_或不希望被缓存就可以通过q个报文头达到目的?

如以下设|,相当于让服务端将对应hq回的响应内容不要在客户端缓存:
  1. Cache-Control: no-cache  


其它h报文头属?/font>

参见Q?a target="_blank">http://en.wikipedia.org/wiki/List_of_HTTP_header_fields

如何讉Kh报文?/font>

׃h报文头是客户端发q来的,服务端当然只能读取了Q以下是HttpServletRequest一些用于读取请求报文头的APIQ?

Java代码 复制代码 收藏代码
  1. //获取h报文中的属性名U?  
  2. java.util.Enumeration<java.lang.String>   getHeaderNames();   
  3.   
  4. //获取指定名称的报文头属性的?  
  5. java.lang.String getHeader(java.lang.String name)   


׃一些请求报文头属?#8220;太著?#8221;了,因此HttpServletRequest为它们提供了VIP的APIQ?

Java代码 复制代码 收藏代码
  1.   
  2. //获取报文头中的Cookie(dCookie的报文头属性)   
  3.  Cookie[]   getCookies() ;   
  4.   
  5. //获取客户端本地化信息Q读?nbsp;Accept-Language 的报文头属性)   
  6. java.util.Locale    getLocale()    
  7.   
  8. //获取h报文体的长度Q读取Content-Length的报文头属性)   
  9. int getContentLength();  


HttpServletRequest可以通过
Java代码 复制代码 收藏代码
  1. HttpSession getSession()   

获取h所兌的HttpSession,其内部的机理是通过dh报文头中Cookie属性的JSESSIONID的|在服务端的一个会话Map中,Ҏq个JSESSIONID获取对应的HttpSession的对象。(q样Q你׃会觉得HttpSession很神U了吧,你自׃可以做一个类似的会话理  Q?

HTTP响应报文解剖

响应报文l构

HTTP的响应报文也׃部分l成Q?strong>响应?响应?响应?/span>
Q:



以下是一个实际的HTTP响应报文Q?



①报文协议及版本;
②状态码及状态描qͼ
③响应报文_也是由多个属性组成;
④响应报文体,x们真正要?#8220;q货”?

响应状态码

和请求报文相比,响应报文多了一?#8220;响应状态码”Q它?#8220;清晰明确”的语a告诉客户端本ơ请求的处理l果?

HTTP的响应状态码?D늻成:

  • 1xx 消息Q一般是告诉客户端,h已经收到了,正在处理Q别?..
  • 2xx 处理成功Q一般表C:h收悉、我明白你要的、请求已受理、已l处理完成等信息.
  • 3xx 重定向到其它地方。它让客L再发起一个请求以完成整个处理?/li>
  • 4xx 处理发生错误Q责d客户端,如客L的请求一个不存在的资源,客户端未被授权,止讉K{?/li>
  • 5xx 处理发生错误Q责d服务端,如服务端抛出异常Q\由出错,HTTP版本不支持等?


以下是几个常见的状态码Q?

200 OK

你最希望看到的,卛_理成功!

303 See Other

我把你redirect到其它的面Q目标的URL通过响应报文头的Location告诉你?
引用
悟空Q师傅给个桃吧,C一天了
唐僧Q我哪有桃啊Q去王母娘娘那找?img src="http://www.iteye.com/images/smiles/icon_wink.gif" alt="" />


304 Not Modified

告诉客户端,你请求的q个资源至你上次取得后,q没有更改,你直接用你本地的~存吧,我很忙哦Q你能不能少来烦我啊Q?

404 Not Found

你最不希望看到的Q即找不到页面。如你在google上找C个页面,点击q个链接q回404Q表C个页面已l被|站删除了,google那边的记录只是美好的回忆?

500 Internal Server Error

看到q个错误Q你应该查查服务端的日志了Q肯定抛Z一堆异常,别睡了,h改BUGdQ?


其它的状态码参见Q?a target="_blank">http://en.wikipedia.org/wiki/List_of_HTTP_status_codes


有些响应码,Web应用服务器会自动l生成。你可以通过HttpServletResponse的API讄状态码Q?

Java代码 复制代码 收藏代码
  1.   
  2. //讄状态码Q状态码在HttpServletResponse中通过一pd的常量预定义了,如SC_ACCEPTEDQSC_OK   
  3. void    setStatus(int sc)   


常见的HTTP响应报文头属?/font>

Cache-Control

响应输出到客L后,服务端通过该报文头属告诉客L如何控制响应内容的缓存?

下面Q的讄让客L对响应内容缓?600U,也即?600U内Q如果客户再ơ访问该资源Q直接从客户端的~存中返回内容给客户Q不要再从服务端获取Q当Ӟq个功能是靠客户端实现的Q服务端只是通过q个属性提C客L“应该q么?#8221;Q做不做Q还是决定于客户端,如果是自己宣U支持HTTP的客LQ则应该这样实玎ͼ?

Java代码 复制代码 收藏代码
  1. Cache-Control: max-age=3600  


ETag

一个代表响应服务端资源Q如面Q版本的报文头属性,如果某个服务端资源发生变化了Q这个ETag׃相应发生变化。它是Cache-Control的有益补充,可以让客L“更智?#8221;地处理什么时候要从服务端取资源,什么时候可以直接从~存中返回响应?

关于ETag的说明,你可以参见:http://en.wikipedia.org/wiki/HTTP_ETag?
Spring 3.0q专门ؓ此提供了一个org.springframework.web.filter.ShallowEtagHeaderFilterQ实现原理很单,对JSP输出的内容MD5Q这样内Ҏ变化ETagq应变化了Q,用于生成响应的ETagQ因东东实可以帮助减少h和响应的交互?

下面是一个ETagQ?
Java代码 复制代码 收藏代码
  1. ETag: "737060cd8c284d8af7ad3082f209582d"  


Location

我们在JSP中让面RedirectC个某个A面中,其实是让客户端再发一个请求到A面Q这个需要Redirect到的A面的URLQ其实就是通过响应报文头的Location属性告知客L的,如下的报文头属性,客户端redirect到iteye的首中Q?

Java代码 复制代码 收藏代码
  1. Location: http://www.iteye.com  


Set-Cookie

服务端可以设|客L的CookieQ其原理是通过q个响应报文头属性实现的Q?

Java代码 复制代码 收藏代码
  1. Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1  



其它HTTP响应报文头属?/font>

更多其它的HTTP响应头报文,参见Q?a target="_blank">http://en.wikipedia.org/wiki/List_of_HTTP_header_fields


如何写HTTPh报文?/font>

在服务端可以通过HttpServletResponse的API写响应报文头的属性:

Java代码 复制代码 收藏代码
  1. //d一个响应报文头属?  
  2. void    setHeader(String name, String value)   


象CookieQLocationq些响应都是有福之hQHttpServletResponse为它们都提供了VIP版的APIQ?
Java代码 复制代码 收藏代码
  1. //dCookie报文头属?  
  2. void addCookie(Cookie cookie)    
  3.   
  4. //不但会设|Location的响应报文头Q还会生?03的状态码呢,两者天仙配?  
  5. void    sendRedirect(String location)   



陕西BOY 2012-06-12 19:02 发表评论
]]>Spring AOP讲解http://www.tkk7.com/haoxuewu/articles/380632.html陕西BOY陕西BOYTue, 12 Jun 2012 10:56:00 GMThttp://www.tkk7.com/haoxuewu/articles/380632.htmlhttp://www.tkk7.com/haoxuewu/comments/380632.htmlhttp://www.tkk7.com/haoxuewu/articles/380632.html#Feedback0http://www.tkk7.com/haoxuewu/comments/commentRss/380632.htmlhttp://www.tkk7.com/haoxuewu/services/trackbacks/380632.html
带有横切逻辑的实?/font>

我们通过具体化代码实C一节所介绍例子的性能监视横切逻辑Qƈ通过动态代理技术对此进行改造。在调用每一个目标类Ҏ时启动方法的性能监视Q在目标cL法调用完成时记录Ҏ的花Ҏ间?

代码清单6-2  ForumServiceQ包含性能监视横切代码
Java代码 复制代码 收藏代码
  1. package com.baobaotao.proxy;   
  2. public class ForumServiceImpl implements ForumService {   
  3.     public void removeTopic(int topicId) {   
  4.                
  5.          //①-1开始对该方法进行性能监视   
  6.         PerformanceMonitor.begin(   
  7.                             "com.baobaotao.proxy.ForumServiceImpl. removeTopic");   
  8.         System.out.println("模拟删除Topic记录:"+topicId);   
  9.         try {   
  10.             Thread.currentThread().sleep(20);   
  11.         } catch (Exception e) {   
  12.             throw new RuntimeException(e);   
  13.         }          
  14.   
  15.          //①-2l束对该Ҏq行性能监视   
  16.         PerformanceMonitor.end();   
  17.     }   
  18.   
  19.     public void removeForum(int forumId) {   
  20.           //②-1开始对该方法进行性能监视   
  21.         PerformanceMonitor.begin(   
  22. "com.baobaotao.proxy.ForumServiceImpl. removeForum");   
  23.         System.out.println("模拟删除Forum记录:"+forumId);   
  24.         try {   
  25.             Thread.currentThread().sleep(40);   
  26.         } catch (Exception e) {   
  27.             throw new RuntimeException(e);   
  28.         }          
  29.   
  30.          //②-2l束对该Ҏq行性能监视   
  31.         PerformanceMonitor.end();   
  32.     }   
  33. }  

代码清单6-2中粗体表C的代码是h横切逻辑特征的代码,每个Servicecd每个业务Ҏ体的前后都执行相同的代码逻辑Q方法调用前启动PerformanceMonitorQ方法调用后通知PerformanceMonitorl束性能监视q给记录性能监视l果?

PerformanceMonitor是性能监视的实现类Q我们给Z个非常简单的实现版本Q其代码如代码清?-3所C:

代码清单6-3  PerformanceMonitor
Java代码 复制代码 收藏代码
  1. package com.baobaotao.proxy;   
  2. public class PerformanceMonitor {   
  3.      //①通过一个ThreadLocal保存调用U程相关的性能监视信息   
  4.     private static ThreadLocal<MethodPerformace> performanceRecord =           
  5.                                 new ThreadLocal<MethodPerformance>();   
  6.        
  7.     //②启动Ҏ一目标Ҏ的性能监视   
  8.      public static void begin(String method) {   
  9.         System.out.println("begin monitor...");   
  10.         MethodPerformance mp = new MethodPerformance(method);   
  11.         performanceRecord.set(mp);   
  12.     }   
  13.     public static void end() {   
  14.         System.out.println("end monitor...");   
  15.         MethodPerformance mp = performanceRecord.get();   
  16.   
  17.          //③打印出方法性能监视的结果信息?  
  18.         mp.printPerformance();   
  19.     }   
  20. }  

ThreadLocal是将非线E安全类攚wؓU程安全cȝ法宝Q在9.2节中我们详l介l这个Java基础知识。PerformanceMonitor提供了两个方法:通过调用begin(String method)Ҏ开始对某个目标cL法的监视Qmethod为目标类Ҏ的全限定名;而end()Ҏl束对目标类Ҏ的监视,q给出性能监视的信息。这两个Ҏ必须配套使用?

用于记录性能监视信息的MethodPerformancecȝ代码如所C:

代码清单6-4  MethodPerformance
Java代码 复制代码 收藏代码
  1. package com.baobaotao.proxy;   
  2. public class MethodPerformance {   
  3.     private long begin;   
  4.     private long end;   
  5.     private String serviceMethod;   
  6.     public MethodPerformance(String serviceMethod){   
  7.        this.serviceMethod = serviceMethod;   
  8.   
  9.        //①记录目标cL法开始执行点的系l时?nbsp;    
  10.        this.begin = System.currentTimeMillis();    
  11.     
  12.     }   
  13.     public void printPerformance(){   
  14.         
  15.         //②获取目标cL法执行完成后的系l时_q进而计出目标cL法执行时?  
  16.         end = System.currentTimeMillis();    
  17.         long elapse = end - begin;   
  18.     
  19.         //③报告目标cL法的执行旉   
  20.         System.out.println(serviceMethod+"p"+elapse+"毫秒?);     
  21.     }   
  22. }  

通过下面的代码测试拥有性能监视能力的ForumServiceImpl业务ҎQ?

Java代码 复制代码 收藏代码
  1. package com.baobaotao.proxy;   
  2.   
  3. public class TestForumService {   
  4.     public static void main(String[] args) {   
  5.         ForumService forumService = new ForumServiceImpl();   
  6.         forumService .removeForum(10);   
  7.        forumService .removeTopic(1012);   
  8.     }   
  9. }  

我们得到以下输出信息Q?
引用
begin monitor... ①removeForum(10)Ҏ的性能监视报告
模拟删除Forum记录:10
end monitor...
com.baobaotao.proxy.ForumServiceImpl.removeForump47毫秒?

begin monitor... ①removeTopic(1012)Ҏ的性能监视报告
模拟删除Topic记录:1012
end monitor...
com.baobaotao.proxy.ForumServiceImpl.removeTopicp26毫秒?/div>
正如代码清单6 2实例所C,当某个方法需要进行性能监视Q就必须调整Ҏ代码Q在Ҏ体前后分别添加上开启性能监视和结束性能监视的代码。这些非业务逻辑的性能监视代码破坏了ForumServiceImpl业务逻辑的纯_Ҏ。我们希望通过代理的方式,业务类Ҏ中开启和l束性能监视的这些横切代码从业务cM完全U除。ƈ通过JDK动态代理技术或CGLib动态代理技术将横切代码动态织入到目标Ҏ的相应位|?

JDK动态代?/font>

JDK 1.3以后QJava提供了动态代理的技术,允许开发者在q行期创建接口的代理实例。在Sun刚推出动态代理时Q还很难惌它有多大的实际用途,现在我们l于发现动态代理是实现AOP的绝好底层技术?

JDK的动态代理主要涉及到java.lang.reflect包中的两个类QProxy和InvocationHandler。其中InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑Qƈ通过反射机制调用目标cȝ代码Q动态将横切逻辑和业务逻辑~织在一赗?

而Proxy利用InvocationHandler动态创Z个符合某一接口的实例,生成目标cȝ代理对象。这栯一定很抽象Q我们马上着手用Proxy和InvocationHandlerq两个魔法戒对上一节中的性能监视代码q行革新?

首先Q我们从业务cForumServiceImpl中删除性能监视的横切代码,使ForumServiceImpl只负责具体的业务逻辑Q如代码清单6-5所C:

代码清单6-5  ForumServiceImplQ移除性能监视横切代码
Java代码 复制代码 收藏代码
  1. package com.baobaotao.proxy;   
  2.   
  3. public class ForumServiceImpl implements ForumService {   
  4.   
  5.     public void removeTopic(int topicId) {   
  6.                                 ①   
  7.         System.out.println("模拟删除Topic记录:"+topicId);   
  8.         try {   
  9.             Thread.currentThread().sleep(20);   
  10.         } catch (Exception e) {   
  11.             throw new RuntimeException(e);   
  12.         }   
  13.                               ①   
  14.     }   
  15.     public void removeForum(int forumId) {   
  16.                           ②   
  17.         System.out.println("模拟删除Forum记录:"+forumId);   
  18.         try {   
  19.             Thread.currentThread().sleep(40);   
  20.         } catch (Exception e) {   
  21.             throw new RuntimeException(e);   
  22.         }   
  23.                           ②   
  24.     }   
  25. }  

在代码清?-5中的①?#9313;处,原来的性能监视代码被移除了Q我们只保留了真正的业务逻辑?

从业务类中移除的性能监视横切代码当然不能漂Q在空气中Q它q得扑ֈ一个安w之所QInvocationHandler是横切代码的安家乐园,我们性能监视的代码安|在PerformanceHandler中,如代码清?-6所C:

Java代码 复制代码 收藏代码
  1. 代码清单6-6  PerformanceHandler   
  2. package com.baobaotao.proxy;   
  3. import java.lang.reflect.InvocationHandler;   
  4. import java.lang.reflect.Method;   
  5.   
  6. public class PerformanceHandler implements InvocationHandler {//①实现InvocationHandler   
  7.     private Object target;   
  8.     public PerformanceHandler(Object target){ //②target为目标的业务c?  
  9.         this.target = target;   
  10.     }   
  11.     public Object invoke(Object proxy, Method method, Object[] args) ③   
  12.             throws Throwable {   
  13.         PerformanceMonitor.begin(target.getClass().getName()+"."+ method. getName());③-1  
  14.         Object obj = method.invoke(target, args);// ③-2通过反射Ҏ调用业务cȝ目标Ҏ   
  15.         PerformanceMonitor.end();③-1  
  16.         return obj;   
  17.     }   
  18. }  


③处invoke()Ҏ中粗体所C部分的代码为性能监视的横切代码,我们发现Q横切代码只出现一ơ,而不是原来那hz各处?#9314;-2处的method.invoke()语句通过Java反射机制间接调用目标对象的方法,q样InvocationHandler的invoke()Ҏ将横切逻辑代码Q?#9314;-1Q和业务cL法的业务逻辑代码Q?#9314;-2Q编l到一起了Q所以我们可以将InvocationHandler看成是一个编l器。下面,我们对这D代码做q一步的说明?

首先Q我们实现InvocationHandler接口Q该接口定义了一?invoke(Object proxy, Method method, Object[] args)的方法,proxy是最l生成的代理实例Q一般不会用刎ͼmethod是被代理目标实例的某个具体方法,通过它可以发L标实例方法的反射调用Qargs是通过被代理实例某一个方法的入参Q在Ҏ反射调用时用?

此外Q我们在构造函数里通过target传入希望被代理的目标对象Q如②处所C,在InvocationHandler接口Ҏinvoke(Object proxy, Method method, Object[] args)里,目标实例传lmethod.invoke()ҎQ调用目标实例的ҎQ如③所C?
下面Q我们通过Proxyl合PerformanceHandler创徏ForumService接口的代理实例,如代码清?-7所C:

代码清单6-7  TestForumServiceQ创Z理实?
Java代码 复制代码 收藏代码
  1. package com.baobaotao.proxy;   
  2. import java.lang.reflect.Proxy;   
  3. public class TestForumService {   
  4.     public static void main(String[] args) {   
  5.                   
  6.                //①希望被代理的目标业务c?  
  7.         ForumService target = new ForumServiceImpl();    
  8.            
  9.                //②目标业务类和横切代码编l到一?  
  10.         PerformanceHandler handler = new PerformanceHandler(target);   
  11.            
  12.                 //③Ҏ~织了目标业务类逻辑和性能监视横切逻辑的InvocationHandler实例创徏代理实例   
  13.         ForumService proxy = (ForumService) Proxy.newProxyInstance(     
  14.                 target.getClass().getClassLoader(),   
  15.                 target.getClass().getInterfaces(),   
  16.                 handler);   
  17.   
  18.                 //④调用代理实例   
  19.         proxy.removeForum(10);      
  20.         proxy.removeTopic(1012);   
  21.     }   
  22. }  

上面的代码完成业务类代码和横切代码的~织工作q生成了代理实例。在②处,我们让PerformanceHandler性能监视横切逻辑~织到ForumService实例中,然后?#9314;处,通过Proxy的newProxyInstance()静态方法ؓ~织了业务类逻辑和性能监视逻辑的handler创徏一个符合ForumService接口的代理实例。该Ҏ的第一个入参ؓcd载器Q第二个入参为创Z理实例所需要实现的一l接口;W三个参数是整合了业务逻辑和横切逻辑的编l器对象?

按照③处的讄方式Q这个代理实例实C目标业务cȝ所有接口,即Forum ServiceImpl的ForumService接口。这P我们可以按照调用ForumService接口实例相同的方式调用代理实例,?#9315;所C。运行以上的代码Q输Z下信息:
引用
begin monitor...
模拟删除Forum记录:10
end monitor...
com.baobaotao.proxy.ForumServiceImpl.removeForump47毫秒?

begin monitor...
模拟删除Topic记录:1012
end monitor...
com.baobaotao.proxy.ForumServiceImpl.removeTopicp26毫秒?/div>
我们发现Q程序的q行效果和直接在业务cM~写性能监视逻辑的效果一_但是在这里,原来分散的横切逻辑代码已经被我们抽取到PerformanceHandler中。当其他业务c(如UserService、SystemService{)的业务方法也需要用性能监视Ӟ我们只要按照代码清单6-7怼的方式,分别为它们创Z理对象就可以了。下面,我们通过时序图描q通过创徏代理对象q行业务Ҏ调用的整体逻辑Q以q一步认识代理对象的本质Q如?-3所C?





我们在上图中使用虚线的方式对通过Proxy创徏的ForumService代理实例加以凸显QForumService代理实例内部利用PerformaceHandler整合横切逻辑和业务逻辑。调用者调用代理对象的removeForum()和removeTopic()ҎӞ上图的内部调用时序清晰地告诉我们实际上所发生的一切?

CGLib动态代?/font>

使用JDK创徏代理有一个限Ӟ卛_只能为接口创Z理实例,q一Ҏ们可从Proxy的接口newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)的方法签名中q得很清楚Q第二个入参interfaces是需要代理实例实现的接口列表。虽焉向接口编E的思想被很多大师人物Q包括Rod JohnsonQ推崇,但在实际开发中Q许多开发者也Ҏ深感困惑Q难道对一个简单业务表的操作也需要老老实实地创徏5个类Q领域对象类、Dao接口QDao实现c,Service接口和Service实现c)吗?N不能直接通过实现cL建程序吗Q对于这个问题,我们很难l出一个孰好孰劣的准确判断Q但我们实发现有很多不使用接口的项目也取得了非常好的效果(包括大家所熟悉的SpringSide开源项目)?

对于没有通过接口定义业务Ҏ的类Q如何动态创Z理实例呢QJDK的代理技术显然已l黔驴技IPCGLib作ؓ一个替代者,填补了这个空~?

CGLib采用非常底层的字节码技术,可以Z个类创徏子类Qƈ在子cM采用Ҏ拦截的技术拦截所有父cL法的调用Qƈ势l入横切逻辑。下面,我们采用CGLib技术,~写一个可以ؓMcd建织入性能监视横切逻辑代理对象的代理创建器Q如代码清单 6-8所C:

代码清单6-8  CglibProxy
Java代码 复制代码 收藏代码
  1. package com.baobaotao.proxy;   
  2. import java.lang.reflect.Method;   
  3. import net.sf.cglib.proxy.Enhancer;   
  4. import net.sf.cglib.proxy.MethodInterceptor;   
  5. import net.sf.cglib.proxy.MethodProxy;   
  6.   
  7. public class CglibProxy implements MethodInterceptor {   
  8.     private Enhancer enhancer = new Enhancer();   
  9.     public Object getProxy(Class clazz) {   
  10.         enhancer.setSuperclass(clazz); //① 讄需要创建子cȝc?  
  11.         enhancer.setCallback(this);    
  12.         return enhancer.create(); //②通过字节码技术动态创建子cd?  
  13.     
  14.     }   
  15.   
  16.         //③拦截父类所有方法的调用   
  17.     public Object intercept(Object obj, Method method, Object[] args,    
  18.             MethodProxy proxy) throws Throwable {   
  19.         PerformanceMonitor.begin(obj.getClass().getName()+"."+method. getName());//③-1   
  20.         Object result=proxy.invokeSuper(obj, args); ③-2    
  21.         PerformanceMonitor.end();//③-1通过代理c调用父cM的方?  
  22.         return result;   
  23.     }   
  24. }  

在上面代码中Q用户可以通过getProxy(Class clazz)Z个类创徏动态代理对象,该代理对象通过扩展clazz创徏代理对象。在q个代理对象中,我们l入性能监视的横切逻辑Q?#9314;-1Q。intercept(Object obj, Method method, Object[] args,MethodProxy proxy)是CGLib定义的Interceptor接口的方法,它拦截所有目标类Ҏ的调用,obj表示目标cȝ实例Qmethod为目标类Ҏ的反对象;args为方法的动态入参;而proxyZ理类实例?

下面Q我们通过CglibProxy为ForumServiceImplcdZ理对象,q测试代理对象的ҎQ如代码清单6-9所C:

代码清单6-9  TestForumServiceQ测试Cglib创徏的代理类
Java代码 复制代码 收藏代码
  1. package com.baobaotao.proxy;   
  2. import java.lang.reflect.Proxy;   
  3. public class TestForumService {   
  4.     public static void main(String[] args) {   
  5.       CglibProxy proxy = new CglibProxy();   
  6.       ForumServiceImpl forumService = ①    
  7.                 (ForumServiceImpl )proxy.getProxy(ForumServiceImpl.class);   
  8.       forumService.removeForum(10);   
  9.       forumService.removeTopic(1023);   
  10.     }   
  11. }  


?#9312;中,我们通过CglibProxy为ForumServiceImpl动态创Z一个织入性能监视逻辑的代理对象,q调用代理类的业务方法。运行上面的代码Q输入以下信息:
引用
begin monitor...
模拟删除Forum记录:10
end monitor...
com.baobaotao.proxy.ForumServiceImpl$$EnhancerByCGLIB$$2a9199c0.removeForump47毫秒?
begin monitor...
模拟删除Topic记录:1023
end monitor...
com.baobaotao.proxy.ForumServiceImpl$$EnhancerByCGLIB$$2a9199c0.removeTopicp16毫秒?/div>
观察以上的输出,除了发现两个业务Ҏ中都l入了性能监控的逻辑外,我们q发C理类的名字是com.baobaotao.proxy.ForumServiceImpl$$EnhancerByCGLIB$$2a9199c0Q这个特D的cd是CGLib为ForumServiceImpl动态创建的子类?

代理知识结

Spring AOP的底层就是通过使用JDK动态代理或CGLib动态代理技术ؓ目标Beanl入横切逻辑。在q里Q我们对前面两节动态创Z理对象作一个小l?

我们虽然通过PerformanceHandler或CglibProxy实现了性能监视横切逻辑的动态织入,但这U实现方式存在三个明N要改q的地方Q?

1Q目标类的所有方法都d了性能监视横切逻辑Q而有Ӟqƈ不是我们所期望的,我们可能只希望对业务cM的某些特定方法添加横切逻辑Q?
2Q我们通过编码的方式指定了织入横切逻辑的织入点Q即在目标类业务Ҏ的开始和l束前织入代码;
3Q我们手工编写代理实例的创徏q程Qؓ不同cdZ理时Q需要分别编写相应的创徏代码Q无法做到通用?

以上三个问题Q在AOP中占用重要的CQ因为Spring AOP的主要工作就是围l以上三点展开QSpring AOP通过PointcutQ切点)指定在哪些类的哪些方法上l入横切逻辑Q通过AdviceQ增强)描述横切逻辑和方法的具体l入点(Ҏ前、方法后、方法的两端{)。此外,Spring通过AdvisorQ切面)Pointcut和Advice两者组装v来。有了Advisor的信息,Spring可以利用JDK或CGLib的动态代理技术采用统一的方式ؓ目标Bean创徏l入切面的代理对象了?

陕西BOY 2012-06-12 18:56 发表评论
]]>Java反射机制http://www.tkk7.com/haoxuewu/articles/380619.html陕西BOY陕西BOYTue, 12 Jun 2012 08:26:00 GMThttp://www.tkk7.com/haoxuewu/articles/380619.htmlhttp://www.tkk7.com/haoxuewu/comments/380619.htmlhttp://www.tkk7.com/haoxuewu/articles/380619.html#Feedback0http://www.tkk7.com/haoxuewu/comments/commentRss/380619.htmlhttp://www.tkk7.com/haoxuewu/services/trackbacks/380619.html
Class反射对象描述c语义结构,可以从Class对象中获取构造函数、成员变量、方法类{类元素的反对象,q以~程的方式通过q些反射对象对目标类对象q行操作。这些反对象类在java.reflect包中定义Q下面是最主要的三个反类Q?
  • ?nbsp; ConstructorQ类的构造函数反类Q通过Class#getConstructors()Ҏ可以获得cȝ所有构造函数反对象数l。在JDK5.0中,q可以通过getConstructor(Class... parameterTypes)获取拥有特定入参的构造函数反对象。Constructor的一个主要方法是newInstance(Object[] initargs)Q通过该方法可以创Z个对象类的实例,相当于new关键字。在JDK5.0中该Ҏ演化为更为灵zȝ形式QnewInstance (Object... initargs)?/li>
  • ?nbsp; MethodQ类Ҏ的反类Q通过Class#getDeclaredMethods()Ҏ可以获取cȝ所有方法反类对象数组Method[]。在JDK5.0中可以通过getDeclaredMethod(String name, Class... parameterTypes)获取特定{֐的方法,name为方法名QClass...为方法入参类型列表。Method最主要的方法是invoke(Object obj, Object[] args)Qobj表示操作的目标对象;args为方法入参,代码清单3 10③处演CZq个反射cȝ使用Ҏ。在JDK 5.0中,该方法的形式调整为invoke(Object obj, Object... args)。此外,Methodq有很多用于获取cL法更多信息的ҎQ?      1QClass getReturnType()Q获取方法的q回值类型;
          2QClass[] getParameterTypes()Q获取方法的入参cd数组Q?
          3QClass[] getExceptionTypes()Q获取方法的异常cd数组Q?
          4QAnnotation[][] getParameterAnnotations()Q获取方法的注解信息QJDK 5.0中的新方法;
  • ?nbsp; FieldQ类的成员变量的反射c,通过Class#getDeclaredFields()Ҏ可以获取cȝ成员变量反射对象数组Q通过Class#getDeclaredField(String name)则可获取某个特定名称的成员变量反对象。FieldcL主要的方法是set(Object obj, Object value)Qobj表示操作的目标对象,通过value为目标对象的成员变量讄倹{如果成员变量ؓ基础cdQ用户可以用FieldcM提供的带cd名的D|方法,如setBoolean(Object obj, boolean value)、setInt(Object obj, int value){?

此外QJavaqؓ包提供了Package反射c,在JDK 5.0中还为注解提供了AnnotatedElement反射cRMQJava的反体pM证了可以通过E序化的方式讉K目标cM所有的元素Q对于private或protected的成员变量和ҎQ只要JVM的安全机制允许,也可以通过反射q行调用Q请看下面的例子Q?

代码清单3-12  PrivateCarReflect

color变量和drive()Ҏ都是U有的,通过cd例变量无法在外部讉KU有变量、调用私有方法的Q但通过反射机制却可以绕q这个限Ӟ


q行该类Q打印出以下信息Q?
引用
drive private car! the color is:U色


在访问private、protected成员变量和方法时必须通过setAccessible(boolean access)Ҏ取消Java语言查,否则抛出IllegalAccessException。如果JVM的安全管理器讄了相应的安全机制Q调用该Ҏ抛出SecurityException?

陕西BOY 2012-06-12 16:26 发表评论
]]>
վ֩ģ壺 þAV뾫Ʒɫҹ| йһëƬѿƵ| ŷŮƵ| һ| 24Сʱձ| ޳AVƬһ| þþ| ۺϾþϵ| Ƶ߹ۿ| vaþþþ| 㻨Ƶۿ| ޳ɫۺվ| һ| һѹۿƵ | ޾ƷɫƵ߹ۿԴ| 츾AV߲| Ұ߹ۿ| ޳˾Ʒþ| ߾Ʒһ㽶| ҹƷþ | ëƬȫһ| ˳վ18ֹþӰԺ | Ļ| ҹav뾫Ʒ| Ůʮ·Ůbbw| 18վڵ | Ůվ߿| þþƷAV鶹| ˳ɵӰ˳9999 | ֻӲˬƬ| 99|| þòþüӰԺ| 츾xxxxx| һҹߴ| ۺ͵Գҳɫ| ҹʱ| ߿ʮ˽վ| ޾ƷƬ߹ۿ| һëƬ| þ91޾ƷĻ| һëƬ޶|