<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    dyerac  
    dyerac In Java
    公告

    日歷
    <2007年7月>
    24252627282930
    1234567
    891011121314
    15161718192021
    22232425262728
    2930311234
    統(tǒng)計
    • 隨筆 - 36
    • 文章 - 10
    • 評論 - 94
    • 引用 - 0

    導(dǎo)航

    常用鏈接

    留言簿(5)

    隨筆分類(49)

    隨筆檔案(36)

    文章分類(11)

    文章檔案(10)

    相冊

    dyerac

    搜索

    •  

    積分與排名

    • 積分 - 79220
    • 排名 - 705

    最新隨筆

    最新評論

    閱讀排行榜

    評論排行榜

     
     這篇文章講的很好
    基本上了解了動態(tài)代理的機制
    就差寫個代碼實驗一下


    ------------------------------------------------------------------------------------------------------------------------


    從JDK1.3開始,Java就引入了動態(tài)代理的概念。動態(tài)代理(Dynamic Proxy)可以幫助你減少代碼行數(shù),真正提高代碼的可復(fù)用度。例如,你不必為所有的類的方法里面都寫上相同的Log代碼行,取而代之的是實用類的動態(tài)代理類。當然,這種便利是有條件的。本文簡單介紹Java動態(tài)代理的原理,并實現(xiàn)一個被代理的Servlet創(chuàng)建,和調(diào)用的過程。
     
    1.代理模式(Proxy Pattern)
    在JDK1.3以前,代理模式就已流行,所以得代理模式是生成一個和類相同接口的代理類,用戶通過使用代理類來封裝某個實現(xiàn)類。如圖1,其目的是加強實現(xiàn)類的某個方法的功能,而不必改變原有的源代碼。

    2.動態(tài)代理(Dynamic Proxy)
    隨著Proxy的流行,Sun把它納入到JDK1.3實現(xiàn)了Java的動態(tài)代理。動態(tài)代理和普通的代理模式的區(qū)別,就是動態(tài)代理中的代理類是由java.lang.reflect.Proxy類在運行期時根據(jù)接口定義,采用Java反射功能動態(tài)生成的。和java.lang.reflect.InvocationHandler結(jié)合,可以加強現(xiàn)有類的方法實現(xiàn)。如圖2,圖中的自定義Handler實現(xiàn)InvocationHandler接口,自定義Handler實例化時,將實現(xiàn)類傳入自定義Handler對象。自定義Handler需要實現(xiàn)invoke方法,該方法可以使用Java反射調(diào)用實現(xiàn)類的實現(xiàn)的方法,同時當然可以實現(xiàn)其他功能,例如在調(diào)用實現(xiàn)類方法前后加入Log。而Proxy類根據(jù)Handler和需要代理的接口動態(tài)生成一個接口實現(xiàn)類的對象。當用戶調(diào)用這個動態(tài)生成的實現(xiàn)類時,實際上是調(diào)用了自定義Handler的invoke方法。
      

    3.動態(tài)代理Servlet
                  雖然Web Application Server的產(chǎn)品很多,但Servlet的處理原理是相似的:動態(tài)加載Servlet,調(diào)用Servlet的init方法(只被調(diào)用一次),并保存到Servlet容器;Servlet使用時,調(diào)用Servlet的service方法。本文動態(tài)代理Servlet接口,使其init和service被調(diào)用時會在控制臺打出方法調(diào)用前后信息。
    首先實現(xiàn)2個Servlet,DefaultServlet和UserServlet
     
    package org.colimas.servlet;
     
    import javax.servlet.Servlet;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
     
    public class DefaultServlet extends HttpServlet implements Servlet {
                  public void init() throws ServletException {
                                super.init();
                                System.out.println(DefaultServlet.class.getName()+":Running init");
                  }
     
                  public String getServletInfo() {
                                return DefaultServlet.class.getName();
                  }
    }
     
    package org.colimas.servlet;
     
    import java.io.IOException;
     
    import javax.servlet.Servlet;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
     
     
    public class UserServlet extends HttpServlet implements Servlet {
     
                  private static final long serialVersionUID = -7016554795165038652L;
                 
                  public void init() throws ServletException {
                                super.init();
                                System.out.println(UserServlet.class.getName()+":Running init");
                  }
                  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                                             
                                System.out.println(UserServlet.class.getName()+":Do UserSErvlet Get");
                  }
                  public String getServletInfo() {
                                return UserServlet.class.getName();
                  }            
                 
     
    }
     
    然后實現(xiàn)InvocationHandler
    package org.colimas.webapp;
     
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
     
    import javax.servlet.Servlet;
     
    public class ServletHandler implements InvocationHandler {
     
                  private Servlet obj;
                 
                  public ServletHandler(Servlet obj){
                                this.obj=obj;
                  }
                  public Object invoke(Object arg0, Method arg1, Object[] arg2)
                                              throws Throwable {
                               
                                if(arg1.getName().compareTo("init")==0) //調(diào)用init時
                                {
                                              System.out.println(obj.getServletInfo()+":Init servlet starting..."); //增加控制臺輸出。
                                              arg1.invoke(obj,arg2); //調(diào)用init方法
                                              System.out.println(obj.getServletInfo()+":Init servlet ending..."); //增加控制臺輸出。
                                }else if(arg1.getName().compareTo("service")==0){ //調(diào)用service時
                                              System.out.println(obj.getServletInfo()+":service starting..."); //增加控制臺輸出。
     
                                              arg1.invoke(obj,arg2); //調(diào)用service方法。
                                              System.out.println(obj.getServletInfo()+":service ending..."); //增加控制臺輸出。
                               
                                }
                                return null;
                  }
     
    }
     
    實現(xiàn)Servlet的調(diào)用
    package org.colimas.webapp;
     
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
     
    import javax.servlet.Servlet;
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
     
    public class ServletWrapperImp {
       
        private Class servletClass;
        private ServletConfig config;
        private String _servletname;
        private Servlet _theServlet;
                  private ServletContext context;
        public ServletWrapperImp(ServletConfig config){
               this.config=config;
               this._servletname=this.config.getServletName();
               this.context=this.config.getServletContext();
        }
       
        public Servlet getServlet() throws ServletException{
     
                                  destroy();
                                  try {
                                                WebAppClassLoader loader=new WebAppClassLoader(this.getClass().getClassLoader()); //自定義class loader
                                                String name=getServletName(); //從ServletConfig中獲得Servlet Name
                                                synchronized (context) {
                                                              Servlet theServlet=context.getServlet(name); //在ServletContext中查找Servlet
                                                              if(theServlet==null){         //如果ServletContext沒有。              
                                                                            servletClass = loader.loadClass(name); //由Class loader 加載Servlet class。
                                                                  theServlet = (Servlet) servletClass.newInstance(); //Servlet實例化。
                                                                  WebAppContext.addServlet(name,theServlet); //將Servlet實例存入ServletContext。
                                                                            InvocationHandler handler=new ServletHandler(theServlet); //自定義ServletHandler,參見ServletHandler類。
                                                                            _theServlet=(Servlet)Proxy.newProxyInstance(theServlet.getClass().getClassLoader(),
                                                                                       new Class[]{Servlet.class},handler); //代理類實例化。
                                                                            _theServlet.init(config); //Servlet代理對象調(diào)用init方法。參見ServletHandler的invoke方法。
                                                                           
                                                              }else{ //ServletContext里已存在。
                                                                            InvocationHandler handler=new ServletHandler(theServlet); //自定義ServletHandler,參見ServletHandler類。
                                                                            _theServlet=(Servlet)Proxy.newProxyInstance(theServlet.getClass().getClassLoader(),
                                                                                       new Class[]{Servlet.class},handler);                 //代理Servlet接口,動態(tài)生成代理類,并實例化。                                  
                                                              }
                                                }
                                                return _theServlet; //返回Servlet代理對象
                                  } catch( ClassNotFoundException ex1 ) {
                                    
                                  } catch( InstantiationException ex ) {
                                     
                                  }catch(IllegalAccessException ex2){
                                               
                                  }
                          return null;
        }
        public void destroy() {
            if (_theServlet != null) {
                          _theServlet.destroy();
            }
        }   
       
        protected String getServletName(){
               return _servletname;
        }
    }
     
    其中的ServletConfig保存Servlet相關(guān)信息。ServletContext保存所有的Servlet對象。WebAppClassLoader為自定義class loader,參見http://blog.csdn.net/tyrone1979/archive/2006/09/03/1164262.aspx
     
    最后編寫測試類Main,該類模擬10個用戶訪問Servlet,5人訪問DefaultServlet,5人訪問UserServlet。
    package org.colimas.main;
     
    import java.io.IOException;
     
    import javax.servlet.Servlet;
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
     
    import org.colimas.webapp.HttpServletRequestWrapper;
    import org.colimas.webapp.HttpServletResponseWrapper;
    import org.colimas.webapp.ServletConfigImpl;
    import org.colimas.webapp.ServletWrapper;
    import org.colimas.webapp.ServletWrapperImp;
    import org.colimas.webapp.WebAppContext;
     
    public class Main {
     
                  private ThreadGroup _threadGroup;
                  private Thread[] _threads;
                  String defaultServletName="org.colimas.servlet.DefaultServlet";
                  String userServletName="org.colimas.servlet.UserServlet";
                  WebAppContext context=WebAppContext.newInstance();     
                 
                  public void doStart(){
                 
                                _threadGroup=new ThreadGroup("SERVLETS");
                                int i=0;
                                _threads=new ServletThread[10]; //模擬10位用戶。
                                for(i=0;i<5;i++){
                                              _threads[i]=new ServletThread(_threadGroup,new Integer(i).toString(),
                                                                          defaultServletName);
                                              _threads[i].start();
                                }
                                for(i=5;i<10;i++){
                                              _threads[i]=new ServletThread(_threadGroup,new Integer(i).toString(),
                                                                          userServletName);
                                              _threads[i].start();
                                }                          
                               
                  }
                  /**
                   * @param args
                   */
                  public static void main(String[] args) {
                                Main _main=new Main();
                                _main.doStart();
                               
                  }
                  //模擬用戶線程
                  private class ServletThread extends Thread{
                               
                                private String servletName;
                               
                                public ServletThread(ThreadGroup group,String threadname,String servletname){
                                              super(group,threadname);
                                              servletName=servletname;
                                }
                                //調(diào)用Servlet的service.
                                public void run() { //用戶調(diào)用Servlet
                                              ServletConfig config=new ServletConfigImpl(servletName,context); //調(diào)用的Servlet信息。
                                              ServletWrapperImp wrapper=new ServletWrapperImp(config);
                                              try {
                                                            Servlet defaultServlet=wrapper.getServlet(); //獲得Servlet對象,實際是Servlet的代理對象
                                                            defaultServlet.service(new HttpServletRequestWrapper(),
                                                                                        new HttpServletResponseWrapper()); 調(diào)用代理對象的service方法,參見ServletHandler的invoke方法。
                                              } catch (ServletException e) {
                                                                                                                    e.printStackTrace();
                                              } catch(IOException e){
                                                           
                                              }
                                }
                               
                  }
    }
    HttpServletRequestWrapper和HttpServletResponseWrapper實現(xiàn)HttpServletRequest,和HttpServletResponse。
    測試結(jié)果如下
    org.colimas.servlet.DefaultServlet:Init servlet starting...
    org.colimas.servlet.DefaultServlet:Running init
    org.colimas.servlet.DefaultServlet:Init servlet ending...
    org.colimas.servlet.UserServlet:Init servlet starting...
    org.colimas.servlet.UserServlet:Running init
    org.colimas.servlet.UserServlet:Init servlet ending...
    org.colimas.servlet.DefaultServlet:service starting...
    org.colimas.servlet.DefaultServlet:service ending...
    org.colimas.servlet.DefaultServlet:service starting...
    org.colimas.servlet.DefaultServlet:service ending...
    org.colimas.servlet.UserServlet:service starting...
    org.colimas.servlet.UserServlet:Do UserSErvlet Get
    org.colimas.servlet.UserServlet:service ending...
    org.colimas.servlet.UserServlet:service starting...
    org.colimas.servlet.UserServlet:Do UserSErvlet Get
    org.colimas.servlet.UserServlet:service ending...
    org.colimas.servlet.UserServlet:service starting...
    org.colimas.servlet.UserServlet:Do UserSErvlet Get
    org.colimas.servlet.UserServlet:service ending...
    org.colimas.servlet.UserServlet:service starting...
    org.colimas.servlet.DefaultServlet:service starting...
    org.colimas.servlet.UserServlet:service starting...
    org.colimas.servlet.DefaultServlet:service starting...
    org.colimas.servlet.DefaultServlet:service starting...
    org.colimas.servlet.UserServlet:Do UserSErvlet Get
    org.colimas.servlet.DefaultServlet:service ending...
    org.colimas.servlet.UserServlet:Do UserSErvlet Get
    org.colimas.servlet.DefaultServlet:service ending...
    org.colimas.servlet.DefaultServlet:service ending...
    org.colimas.servlet.UserServlet:service ending...
    org.colimas.servlet.UserServlet:service ending...
     
    2個Servlet第一次Load時初始化,被調(diào)用init,之后保存到ServletContext中。第二次直接從ServletContext獲得,執(zhí)行service。紅字表示代理類里增加的輸出結(jié)果。
     
    4.動態(tài)代理的限制
                  JDK的動態(tài)代理并不能隨心所欲的代理所有的類。Proxy.newProxyInstance方法的第二個參數(shù)只能是接口數(shù)組, 也就是Proxy只能代理接口。

     

    posted on 2007-07-24 15:10 dyerac in java... 閱讀(1885) 評論(0)  編輯  收藏 所屬分類: JavaSE
     
    Copyright © dyerac in java... Powered by: 博客園 模板提供:滬江博客
    主站蜘蛛池模板: 日韩精品无码免费专区午夜| 亚洲AV无码乱码在线观看| 人人鲁免费播放视频人人香蕉| 亚洲第一页在线播放| 在线观看亚洲成人| 国产成人在线观看免费网站 | 无码免费一区二区三区免费播放| 久久亚洲精品无码av| 亚洲av无码国产综合专区| 亚洲VA成无码人在线观看天堂| 亚洲av无码成人精品区在线播放| 成年女人午夜毛片免费看| 91禁漫免费进入| 国产真人无码作爱视频免费| 一级毛片免费在线播放| 小说专区亚洲春色校园| 亚洲最大无码中文字幕| 亚洲人成激情在线播放| 亚洲成aⅴ人片在线影院八| 亚洲一区精品中文字幕| 亚洲国产老鸭窝一区二区三区| 亚洲色成人网站WWW永久| 亚洲一区二区三区免费| 亚洲?V乱码久久精品蜜桃| 国产免费看插插插视频| 国产麻豆剧传媒精品国产免费| 在线免费观看毛片网站| 最近最好的中文字幕2019免费| 无遮免费网站在线入口| 亚洲精品视频免费在线观看| 亚洲黄色片免费看| 95免费观看体验区视频| 日本视频一区在线观看免费| 亚洲精品视频免费在线观看| 99在线精品免费视频九九视| 亚洲人成网站免费播放| 日韩免费高清一级毛片在线| 日本免费电影一区| www.亚洲精品.com| 亚洲综合色区在线观看| 亚洲成av人片在线观看无码不卡|