<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
    統計
    • 隨筆 - 36
    • 文章 - 10
    • 評論 - 94
    • 引用 - 0

    導航

    常用鏈接

    留言簿(5)

    隨筆分類(49)

    隨筆檔案(36)

    文章分類(11)

    文章檔案(10)

    相冊

    dyerac

    搜索

    •  

    積分與排名

    • 積分 - 79235
    • 排名 - 705

    最新隨筆

    最新評論

    閱讀排行榜

    評論排行榜

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


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


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

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

    3.動態代理Servlet
                  雖然Web Application Server的產品很多,但Servlet的處理原理是相似的:動態加載Servlet,調用Servlet的init方法(只被調用一次),并保存到Servlet容器;Servlet使用時,調用Servlet的service方法。本文動態代理Servlet接口,使其init和service被調用時會在控制臺打出方法調用前后信息。
    首先實現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();
                  }            
                 
     
    }
     
    然后實現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) //調用init時
                                {
                                              System.out.println(obj.getServletInfo()+":Init servlet starting..."); //增加控制臺輸出。
                                              arg1.invoke(obj,arg2); //調用init方法
                                              System.out.println(obj.getServletInfo()+":Init servlet ending..."); //增加控制臺輸出。
                                }else if(arg1.getName().compareTo("service")==0){ //調用service時
                                              System.out.println(obj.getServletInfo()+":service starting..."); //增加控制臺輸出。
     
                                              arg1.invoke(obj,arg2); //調用service方法。
                                              System.out.println(obj.getServletInfo()+":service ending..."); //增加控制臺輸出。
                               
                                }
                                return null;
                  }
     
    }
     
    實現Servlet的調用
    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代理對象調用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接口,動態生成代理類,并實例化。                                  
                                                              }
                                                }
                                                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相關信息。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;
                                }
                                //調用Servlet的service.
                                public void run() { //用戶調用Servlet
                                              ServletConfig config=new ServletConfigImpl(servletName,context); //調用的Servlet信息。
                                              ServletWrapperImp wrapper=new ServletWrapperImp(config);
                                              try {
                                                            Servlet defaultServlet=wrapper.getServlet(); //獲得Servlet對象,實際是Servlet的代理對象
                                                            defaultServlet.service(new HttpServletRequestWrapper(),
                                                                                        new HttpServletResponseWrapper()); 調用代理對象的service方法,參見ServletHandler的invoke方法。
                                              } catch (ServletException e) {
                                                                                                                    e.printStackTrace();
                                              } catch(IOException e){
                                                           
                                              }
                                }
                               
                  }
    }
    HttpServletRequestWrapper和HttpServletResponseWrapper實現HttpServletRequest,和HttpServletResponse。
    測試結果如下
    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時初始化,被調用init,之后保存到ServletContext中。第二次直接從ServletContext獲得,執行service。紅字表示代理類里增加的輸出結果。
     
    4.動態代理的限制
                  JDK的動態代理并不能隨心所欲的代理所有的類。Proxy.newProxyInstance方法的第二個參數只能是接口數組, 也就是Proxy只能代理接口。

     

    posted on 2007-07-24 15:10 dyerac in java... 閱讀(1886) 評論(0)  編輯  收藏 所屬分類: JavaSE
     
    Copyright © dyerac in java... Powered by: 博客園 模板提供:滬江博客
    主站蜘蛛池模板: 国产精品偷伦视频免费观看了| 成人免费区一区二区三区| 亚洲国产电影av在线网址| 东北美女野外bbwbbw免费| 1区1区3区4区产品亚洲| 天天摸天天碰成人免费视频| 本道天堂成在人线av无码免费| 久久久久亚洲av无码专区| 国产精品免费一级在线观看| 国产白丝无码免费视频| 国产亚洲精彩视频| 亚洲无删减国产精品一区| 麻豆精品国产免费观看| 热re99久久6国产精品免费| 亚洲国产成人久久综合| 亚洲网址在线观看你懂的| 亚洲av无码不卡私人影院| 国产成人精品免费视频大| 精品国产免费人成网站| 亚洲成年网站在线观看| 国产成A人亚洲精V品无码性色 | 男人免费视频一区二区在线观看| 国产成人A人亚洲精品无码| 国产女高清在线看免费观看| 九九精品成人免费国产片| 综合一区自拍亚洲综合图区| 亚洲美免无码中文字幕在线| 亚洲美女在线国产| 久久综合AV免费观看| 午夜精品免费在线观看| yellow视频免费在线观看| 中文字幕乱码亚洲精品一区| 亚洲AV日韩AV高潮无码专区| 亚洲人成无码www久久久| 国产精品久久久久免费a∨ | 真人做人试看60分钟免费视频| 中国极品美軳免费观看| 亚洲av日韩av永久在线观看 | 久久国产乱子伦精品免费不卡 | 久久久久高潮毛片免费全部播放| 一级视频免费观看|