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

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

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

    Rising Sun

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      148 隨筆 :: 0 文章 :: 22 評(píng)論 :: 0 Trackbacks

    #

    http://sunnylocus.iteye.com/blog/342996
       大多數(shù)程序員都知道Servlet的生命周期,簡單的概括這就分為四步:servlet類加載--->實(shí)例化--->服務(wù)--->銷毀。對(duì)這個(gè)過程只是膚淺了解下,對(duì)于servlet何時(shí)被銷毀,還是不太情楚。下面我們描述一下Tomcat與Servlet是如何工作的,首先看下面的時(shí)序圖.

    1、Web Client 向Servlet容器(Tomcat)發(fā)出Http請(qǐng)求

    2、Servlet容器接收Web Client的請(qǐng)求

    3、Servlet容器創(chuàng)建一個(gè)HttpRequest對(duì)象,將Web Client請(qǐng)求的信息封裝到這個(gè)對(duì)象中

    4、Servlet容器創(chuàng)建一個(gè)HttpResponse對(duì)象

    5、Servlet容器調(diào)用HttpServlet對(duì)象的service方法,把HttpRequest對(duì)象與HttpResponse對(duì)象作為參數(shù)

         傳給 HttpServlet對(duì)象

    6、HttpServlet調(diào)用HttpRequest對(duì)象的有關(guān)方法,獲取Http請(qǐng)求信息

    7、HttpServlet調(diào)用HttpResponse對(duì)象的有關(guān)方法,生成響應(yīng)數(shù)據(jù)

    8、Servlet容器把HttpServlet的響應(yīng)結(jié)果傳給Web Client

     

    對(duì)于Servlet容器(Tomcat)與HttpServlet是怎樣進(jìn)行交互的呢,看下類圖

    Servlet的框架是由兩個(gè)Java包組成的:javax.servlet與javax.servlet.http。在javax.servlet包中定義了所有的Servlet類都必須實(shí)現(xiàn)或者擴(kuò)展的通用接口和類。在javax.servlet.http包中定義了采用Http協(xié)議通信的HttpServlet類。Servlet的框架的核心是javax.servlet.Servlet接口,所有的Servlet都必須實(shí)現(xiàn)這個(gè)接口。

    在Servlet接口中定義了5個(gè)方法,

    其中3個(gè)方法代表了Servlet的生命周期:

    1、init方法:負(fù)責(zé)初始化Servlet對(duì)象。

    2、service方法:負(fù)責(zé)響應(yīng)客戶的請(qǐng)求。

    3、destroy方法:當(dāng)Servlet對(duì)象退出生命周期時(shí),負(fù)責(zé)釋放占用的資源。

     

    一、創(chuàng)建Servlet對(duì)象的時(shí)機(jī)

    1、Servlet容器啟動(dòng)時(shí):讀取web.xml配置文件中的信息,構(gòu)造指定的Servlet對(duì)象,創(chuàng)建ServletConfig對(duì)象,同時(shí)將ServletConfig對(duì)象作為參數(shù)來調(diào)用Servlet對(duì)象的init方法。

    2、在Servlet容器啟動(dòng)后:客戶首次向Servlet發(fā)出請(qǐng)求,Servlet容器會(huì)判斷內(nèi)存中是否存在指定的Servlet對(duì)象,如果沒有則創(chuàng)建它,然后根據(jù)客戶的請(qǐng)求創(chuàng)建HttpRequest、       HttpResponse對(duì)象,從而調(diào)用Servlet

         對(duì)象的service方法。

    3、Servlet的類文件被更新后,重新創(chuàng)建Servlet

          Servlet容器在啟動(dòng)時(shí)自動(dòng)創(chuàng)建Servlet,這是由在web.xml文件中為Servlet設(shè)置的<load-on-startup>屬性決定

          的。從中我們也能看到同一個(gè)類型的Servlet對(duì)象在Servlet容器中以單例的形式存在。

    二、銷毀Servlet對(duì)象的時(shí)機(jī)

    1、Servlet容器停止或者重新啟動(dòng):Servlet容器調(diào)用Servlet對(duì)象的destroy方法來釋放資源。以上所講的就是Servlet對(duì)象的生命周期。那么Servlet容器如何知道創(chuàng)建哪一個(gè)Servlet對(duì)象?

    Servlet對(duì)象如何配置?實(shí)際上這些信息是通過讀取web.xml配置文件來實(shí)現(xiàn)的。

    我們來看一下web.xml文件中的Servlet對(duì)象的配置節(jié)信息

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

    <servlet>

        <servlet-name>action<servlet-name>

        <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>

        <init-param>

            <param-name>config</param-name>

            <param-value>/WEB-INF/struts-config.xml</param-value>

        </init-param>

        <init-param>

            <param-name>detail</param-name>

            <param-value>2</param-value>

        </init-param>

        <init-param>

            <param-name>debug</param-name>

            <param-value>2</param-value>

        </init-param>

        <load-on-startup>2</load-on-startup>

    </servlet>

    <servlet-mapping>

        <servlet-name>action</servlet-name>

        <url-pattern>*.do</url-pattern>

    </servlet-mapping>

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

    下面對(duì)上面的配置節(jié)信息進(jìn)行解析

    servlet-name:Servlet對(duì)象的名稱

    servlet-class:創(chuàng)建Servlet對(duì)象所要調(diào)用的類

    param-name:參數(shù)名稱

    param-value:參數(shù)值

    load-on-startup:Servlet容器啟動(dòng)時(shí)加載Servlet對(duì)象的順序

    servlet-mapping/servlet-name:要與servlet中的servlet-name配置節(jié)內(nèi)容對(duì)應(yīng)

    url-pattern:客戶訪問的Servlet的相對(duì)URL路徑

     

           當(dāng)Servlet容器啟動(dòng)的時(shí)候讀取<servlet>配置節(jié)信息,根據(jù)<servlet-class>配置節(jié)信息創(chuàng)建Servlet對(duì)象,同時(shí)根據(jù)<init-param>配置節(jié)信息創(chuàng)建HttpServletConfig對(duì)象,然后執(zhí)行Servlet對(duì)象的init方法,并且根據(jù)<load-on-startup>配置節(jié)信息來決定創(chuàng)建Servlet對(duì)象的順序,如果此配置節(jié)信息為負(fù)數(shù)或者沒有配置,那么在Servlet容器啟動(dòng)時(shí),將不加載此Servlet對(duì)象。當(dāng)客戶訪問Servlet容器時(shí),Servlet容器根據(jù)客戶訪問的URL地址,通過<servlet-mapping>配置節(jié)中的<url-pattern>配置節(jié)信息找到指定的Servlet對(duì)象,并調(diào)用此Servlet對(duì)象的service方法。

     

    為了驗(yàn)證下,我新建了一個(gè)web app工程,新建一個(gè)Servlet,如下:

    Java代碼  收藏代碼
    1. package com.tdt.servlet;  
    2.   
    3. import java.io.IOException;  
    4. import java.io.PrintWriter;  
    5. import javax.servlet.ServletException;  
    6. import javax.servlet.http.HttpServlet;  
    7. import javax.servlet.http.HttpServletRequest;  
    8. import javax.servlet.http.HttpServletResponse;  
    9.   
    10. public class TestServlet extends HttpServlet {  
    11.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
    12.             throws ServletException, IOException {  
    13.         this.doPost(request, response);  
    14.     }  
    15.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
    16.             throws ServletException, IOException {  
    17.   
    18.         response.setContentType("text/html");  
    19.         PrintWriter out = response.getWriter();  
    20.         out.println("Hello,this is a test");  
    21.       
    22.         out.flush();  
    23.         out.close();  
    24.     }  
    25.   
    26.     public void destroy() {  
    27.         System.err.println(getServletName()+"生命周期結(jié)束");;  
    28.     }  
    29.       
    30.     public void init() throws ServletException {  
    31.         System.out.println(getServletName()+"執(zhí)行初始化");  
    32.     }  
    33. }  

     當(dāng)servlet被銷毀時(shí)會(huì)在控制臺(tái)上打印提示語句,不過我發(fā)現(xiàn)在tomcat中,只要不停止web容器,servlet是不會(huì)被銷毀的。有沒有什么方法,當(dāng)service方法執(zhí)行完畢就銷毀這個(gè)servlet呢,我問了下老師,他說寫一個(gè)監(jiān)聽器,不過我不知道怎么去實(shí)現(xiàn)它,如果有朋友知道實(shí)現(xiàn)的過程,還請(qǐng)賜教。

    posted @ 2013-03-05 14:09 brock 閱讀(241) | 評(píng)論 (0)編輯 收藏


    來源:struts2開發(fā)組 翻譯:tianxinet(胖猴) 
    Action 類: 
    • Struts1要求Action類繼承一個(gè)抽象基類。Struts1的一個(gè)普遍問題是使用抽象類編程而不是接口。 
    • Struts 2 Action類可以實(shí)現(xiàn)一個(gè)Action接口,也可實(shí)現(xiàn)其他接口,使可選和定制的服務(wù)成為可能。Struts2提供一個(gè)ActionSupport基類去實(shí)現(xiàn) 常用的接口。Action接口不是必須的,任何有execute標(biāo)識(shí)的POJO對(duì)象都可以用作Struts2的Action對(duì)象。 
    線程模式: 
    • Struts1 Action是單例模式并且必須是線程安全的,因?yàn)閮H有Action的一個(gè)實(shí)例來處理所有的請(qǐng)求。單例策略限制了Struts1 Action能作的事,并且要在開發(fā)時(shí)特別小心。Action資源必須是線程安全的或同步的。 
    • Struts2 Action對(duì)象為每一個(gè)請(qǐng)求產(chǎn)生一個(gè)實(shí)例,因此沒有線程安全問題。(實(shí)際上,servlet容器給每個(gè)請(qǐng)求產(chǎn)生許多可丟棄的對(duì)象,并且不會(huì)導(dǎo)致性能和垃圾回收問題) 
    Servlet 依賴: 
    • Struts1 Action 依賴于Servlet API ,因?yàn)楫?dāng)一個(gè)Action被調(diào)用時(shí)HttpServletRequest 和 HttpServletResponse 被傳遞給execute方法。 
    • Struts 2 Action不依賴于容器,允許Action脫離容器單獨(dú)被測(cè)試。如果需要,Struts2 Action仍然可以訪問初始的request和response。但是,其他的元素減少或者消除了直接訪問HttpServetRequest 和 HttpServletResponse的必要性。 
    可測(cè)性: 
    • 測(cè)試Struts1 Action的一個(gè)主要問題是execute方法暴露了servlet API(這使得測(cè)試要依賴于容器)。一個(gè)第三方擴(kuò)展--Struts TestCase--提供了一套Struts1的模擬對(duì)象(來進(jìn)行測(cè)試)。 
    • Struts 2 Action可以通過初始化、設(shè)置屬性、調(diào)用方法來測(cè)試,“依賴注入”支持也使測(cè)試更容易。 
    捕獲輸入: 
    • Struts1 使用ActionForm對(duì)象捕獲輸入。所有的ActionForm必須繼承一個(gè)基類。因?yàn)槠渌鸍avaBean不能用作ActionForm,開發(fā)者經(jīng)常創(chuàng)建多余的類捕獲輸入。動(dòng)態(tài)Bean(DynaBeans)可以作為創(chuàng)建傳統(tǒng)ActionForm的選擇,但是,開發(fā)者可能是在重新描述(創(chuàng)建)已經(jīng)存在的JavaBean(仍然會(huì)導(dǎo)致有冗余的javabean)。 
    • Struts 2直接使用Action屬性作為輸入屬性,消除了對(duì)第二個(gè)輸入對(duì)象的需求。輸入屬性可能是有自己(子)屬性的rich對(duì)象類型。Action屬性能夠通過 web頁面上的taglibs訪問。Struts2也支持ActionForm模式。rich對(duì)象類型,包括業(yè)務(wù)對(duì)象,能夠用作輸入/輸出對(duì)象。這種 ModelDriven 特性簡化了taglib對(duì)POJO輸入對(duì)象的引用。 
    表達(dá)式語言: 
    • Struts1 整合了JSTL,因此使用JSTL EL。這種EL有基本對(duì)象圖遍歷,但是對(duì)集合和索引屬性的支持很弱。 
    • Struts2可以使用JSTL,但是也支持一個(gè)更強(qiáng)大和靈活的表達(dá)式語言--"Object Graph Notation Language" (OGNL). 
    綁定值到頁面(view): 
    • Struts 1使用標(biāo)準(zhǔn)JSP機(jī)制把對(duì)象綁定到頁面中來訪問。 
    • Struts 2 使用 "ValueStack"技術(shù),使taglib能夠訪問值而不需要把你的頁面(view)和對(duì)象綁定起來。ValueStack策略允許通過一系列名稱相同但類型不同的屬性重用頁面(view)。 
      
    類型轉(zhuǎn)換: 
    • Struts 1 ActionForm 屬性通常都是String類型。Struts1使用Commons-Beanutils進(jìn)行類型轉(zhuǎn)換。每個(gè)類一個(gè)轉(zhuǎn)換器,對(duì)每一個(gè)實(shí)例來說是不可配置的。 
    • Struts2 使用OGNL進(jìn)行類型轉(zhuǎn)換。提供基本和常用對(duì)象的轉(zhuǎn)換器。 
    校驗(yàn): 
    • Struts 1支持在ActionForm的validate方法中手動(dòng)校驗(yàn),或者通過Commons Validator的擴(kuò)展來校驗(yàn)。同一個(gè)類可以有不同的校驗(yàn)內(nèi)容,但不能校驗(yàn)子對(duì)象。 
    • Struts2支持通過validate方法和XWork校驗(yàn)框架來進(jìn)行校驗(yàn)。XWork校驗(yàn)框架使用為屬性類類型定義的校驗(yàn)和內(nèi)容校驗(yàn),來支持chain校驗(yàn)子屬性 
    Action執(zhí)行的控制: 
    • Struts1支持每一個(gè)模塊有單獨(dú)的Request Processors(生命周期),但是模塊中的所有Action必須共享相同的生命周期。 
    • Struts2支持通過攔截器堆棧(Interceptor Stacks)為每一個(gè)Action創(chuàng)建不同的生命周期。堆棧能夠根據(jù)需要和不同的Action一起使用。

    posted @ 2013-03-05 10:59 brock 閱讀(228) | 評(píng)論 (0)編輯 收藏

         摘要: http://penghuaiyi.iteye.com/blog/182616這段時(shí)間,看了一些Spring文檔和資料,對(duì)其有了一個(gè)基本的了解。Spring的核心技術(shù)由兩大部分組成:IoC和AOP,下面我們就分別對(duì)它們進(jìn)行介紹。 1  IoC技術(shù) 1.1  預(yù)備知識(shí)      IoC即Inversion of...  閱讀全文
    posted @ 2013-03-05 10:37 brock 閱讀(322) | 評(píng)論 (0)編輯 收藏

         摘要: 1. Struts2架構(gòu)圖 這是Struts2官方站點(diǎn)提供的Struts 2 的整體結(jié)構(gòu)。 2. Struts2部分類介紹 這部分從Struts2參考文檔中翻譯就可以了。 ActionMapper         ActionMapper其實(shí)是HttpServletRequest...  閱讀全文
    posted @ 2013-03-05 09:31 brock 閱讀(214) | 評(píng)論 (0)編輯 收藏

         摘要: http://singleant.iteye.com/blog/1177358 接上文 啃啃老菜: Spring IOC核心源碼學(xué)習(xí)(一) ,本文將以 ClassPathXmlApplicationContext 這個(gè)容器的實(shí)現(xiàn)作為基礎(chǔ),學(xué)習(xí)容器的初始化過程。ClassPathXmlApplicationContext 類體系結(jié)構(gòu)以下是&...  閱讀全文
    posted @ 2013-02-28 11:04 brock 閱讀(822) | 評(píng)論 (0)編輯 收藏

    本文主要以spring ioc容器基本代碼骨架為切入點(diǎn),理解ioc容器的基本代碼組件結(jié)構(gòu),各代碼組件細(xì)節(jié)剖析將放在后面的學(xué)習(xí)文章里。

     http://www.iteye.com/topic/1113459

    關(guān)于IOC容器

    IoC容器:最主要是完成了完成對(duì)象的創(chuàng)建和依賴的管理注入等等。

    先從我們自己設(shè)計(jì)這樣一個(gè)視角來考慮:

    所謂控制反轉(zhuǎn),就是把原先我們代碼里面需要實(shí)現(xiàn)的對(duì)象創(chuàng)建、依賴的代碼,反轉(zhuǎn)給容器來幫忙實(shí)現(xiàn)。那么必然的我們需要?jiǎng)?chuàng)建一個(gè)容器,同時(shí)需要一種描述來讓容器知道需要?jiǎng)?chuàng)建的對(duì)象與對(duì)象的關(guān)系。這個(gè)描述最具體表現(xiàn)就是我們可配置的文件。

    對(duì)象和對(duì)象關(guān)系怎么表示?

    可以用xmlproperties文件等語義化配置文件表示。

    描述對(duì)象關(guān)系的文件存放在哪里?

    可能是classpathfilesystem,或者是URL網(wǎng)絡(luò)資源,servletContext等。

    回到正題,有了配置文件,還需要對(duì)配置文件解析。

    不同的配置文件對(duì)對(duì)象的描述不一樣,如標(biāo)準(zhǔn)的,自定義聲明式的,如何統(tǒng)一? 在內(nèi)部需要有一個(gè)統(tǒng)一的關(guān)于對(duì)象的定義,所有外部的描述都必須轉(zhuǎn)化成統(tǒng)一的描述定義。

    如何對(duì)不同的配置文件進(jìn)行解析?需要對(duì)不同的配置文件語法,采用不同的解析器。

     

    基于以上問題,對(duì)應(yīng)過來,剛好是 spring ioc 容器抽象的的幾個(gè)主要接口:

    Resource

    BeanDefinition

    BeanDefinitionReader

    BeanFactory

    ApplicationContext

    以上五個(gè)都是接口,都有各式各樣的實(shí)現(xiàn),正是這5個(gè)接口定義了spring ioc容器的基本代碼組件結(jié)構(gòu)。而其組件各種實(shí)現(xiàn)的組合關(guān)系組成了一個(gè)運(yùn)行時(shí)的具體容器。

     

    各代碼組件詳解

    1.Resource

    是對(duì)資源的抽象,每一個(gè)接口實(shí)現(xiàn)類都代表了一種資源類型,如ClasspathResourceURLResourceFileSystemResource等。每一個(gè)資源類型都封裝了對(duì)某一種特定資源的訪問策略。它是spring資源訪問策略的一個(gè)基礎(chǔ)實(shí)現(xiàn),應(yīng)用在很多場(chǎng)景。

     

     

     

     

    具體可以參考文章:

    Spring 資源訪問剖析和策略模式應(yīng)用

    http://www.ibm.com/developerworks/cn/java/j-lo-spring-resource/index.html

     

     

    2.BeanDefinition

    用來抽象和描述一個(gè)具體bean對(duì)象。是描述一個(gè)bean對(duì)象的基本數(shù)據(jù)結(jié)構(gòu)。

    3.BeanDefinitionReader

    BeanDefinitionReader將外部資源對(duì)象描述的bean定義統(tǒng)一轉(zhuǎn)化為統(tǒng)一的內(nèi)部數(shù)據(jù)結(jié)構(gòu)BeanDefinition。對(duì)應(yīng)不同的描述需要有不同的Reader。如XmlBeanDefinitionReader用來讀取xml描述配置的bean對(duì)象。



     

    4.BeanFactory

    用來定義一個(gè)很純粹的bean容器。它是一個(gè)bean容器的必備結(jié)構(gòu)。同時(shí)和外部應(yīng)用環(huán)境等隔離。BeanDefinition是它的基本數(shù)據(jù)結(jié)構(gòu)。它維護(hù)一個(gè)BeanDefinitions Map,并可根據(jù)BeanDefinition的描述進(jìn)行bean的創(chuàng)建和管理。



     

    5.ApplicationContext

    從名字來看叫應(yīng)用上下文,是和應(yīng)用環(huán)境息息相關(guān)的。沒錯(cuò)這個(gè)就是我們平時(shí)開發(fā)中經(jīng)常直接使用打交道的一個(gè)類,應(yīng)用上下文,或者也叫做spring容器。其實(shí)它的基本實(shí)現(xiàn)是會(huì)持有一個(gè)BeanFactory對(duì)象,并基于此提供一些包裝和功能擴(kuò)展。為什么要這么做呢?因?yàn)?span style="font-size: 11pt; font-family: 'Courier New';">BeanFactory實(shí)現(xiàn)了一個(gè)容器基本結(jié)構(gòu)和功能,但是與外部環(huán)境隔離。那么讀取配置文件,并將配置文件解析成BeanDefinition,然后注冊(cè)到BeanFactory的這一個(gè)過程的封裝自然就需要ApplicationContextApplicationContext和應(yīng)用環(huán)境細(xì)細(xì)相關(guān),常見實(shí)現(xiàn)有ClasspathXmlApplicationContext,FileSystemXmlApplicationContext,WebApplicationContext等。ClasspathxmlFileSystemWeb等詞都代表了應(yīng)用和環(huán)境相關(guān)的一些意思,從字面上不難理解各自代表的含義。

    當(dāng)然ApplicationContextBeanFactory的區(qū)別遠(yuǎn)不止于此,有:

    1.  資源訪問功能:在ResourceResourceLoader的基礎(chǔ)上可以靈活的訪問不同的資源。

    2.  支持不同的信息源。

    3.  支持應(yīng)用事件:繼承了接口ApplicationEventPublisher,這樣在上下文中為bean之間提供了事件機(jī)制。

    ……



     

     

    以上5個(gè)組件基本代表了ioc容器的一個(gè)最基本組成,而組件的組合是放在ApplicationContext的實(shí)現(xiàn)這一層來完成。

     

    以ClasspathXmlApplicationContext 容器實(shí)現(xiàn)為例,其組合關(guān)系如下:

     


    ClassPathXmlApplicationContext的refresh() 方法負(fù)責(zé)完成了整個(gè)容器的初始化。

    為什么叫refresh?也就是說其實(shí)是刷新的意思,該IOC容器里面維護(hù)了一個(gè)單例的BeanFactory,如果bean的配置有修改,也可以直接調(diào)用refresh方法,它將銷毀之前的BeanFactory,重新創(chuàng)建一個(gè)BeanFactory。所以叫refresh也是能理解的。

    以下是Refresh的基本步驟:
    1.把配置xml文件轉(zhuǎn)換成resource。resource的轉(zhuǎn)換是先通過ResourcePatternResolver來解析可識(shí)別格式的配置文件的路徑
    (如"classpath*:"等),如果沒有指定格式,默認(rèn)會(huì)按照類路徑的資源來處理。 
    2.利用XmlBeanDefinitionReader完成對(duì)xml的解析,將xml Resource里定義的bean對(duì)象轉(zhuǎn)換成統(tǒng)一的BeanDefinition。
    3.將BeanDefinition注冊(cè)到BeanFactory,完成對(duì)BeanFactory的初始化。BeanFactory里將會(huì)維護(hù)一個(gè)BeanDefinition的Map。

    當(dāng)getBean的時(shí)候就會(huì)根據(jù)調(diào)用BeanFactory,根據(jù)bean的BeanDifinition來實(shí)例化一個(gè)bean。當(dāng)然根據(jù)bean的lazy-init、protetype等屬性設(shè)置不同以上過程略有差別。

     

    refresh()代碼如下:

    Java代碼  收藏代碼
    1. public void refresh() throws BeansException, IllegalStateException {  
    2.     synchronized (this.startupShutdownMonitor) {  
    3.         // Prepare this context for refreshing.  
    4.         prepareRefresh();  
    5.   
    6.         // Tell the subclass to refresh the internal bean factory.  
    7.         ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();  
    8.   
    9.         // Prepare the bean factory for use in this context.  
    10.         prepareBeanFactory(beanFactory);  
    11.   
    12.         try {  
    13.             // Allows post-processing of the bean factory in context subclasses.  
    14.             postProcessBeanFactory(beanFactory);  
    15.   
    16.             // Invoke factory processors registered as beans in the context.  
    17.             invokeBeanFactoryPostProcessors(beanFactory);  
    18.   
    19.             // Register bean processors that intercept bean creation.  
    20.             registerBeanPostProcessors(beanFactory);  
    21.   
    22.             // Initialize message source for this context.  
    23.             initMessageSource();  
    24.   
    25.             // Initialize event multicaster for this context.  
    26.             initApplicationEventMulticaster();  
    27.   
    28.             // Initialize other special beans in specific context subclasses.  
    29.             onRefresh();  
    30.   
    31.             // Check for listener beans and register them.  
    32.             registerListeners();  
    33.   
    34.             // Instantiate all remaining (non-lazy-init) singletons.  
    35.             finishBeanFactoryInitialization(beanFactory);  
    36.   
    37.             // Last step: publish corresponding event.  
    38.             finishRefresh();  
    39.         }  
    40.   
    41.         catch (BeansException ex) {  
    42.             // Destroy already created singletons to avoid dangling resources.  
    43.             beanFactory.destroySingletons();  
    44.   
    45.             // Reset 'active' flag.  
    46.             cancelRefresh(ex);  
    47.   
    48.             // Propagate exception to caller.  
    49.             throw ex;  
    50.         }  
    51.     }  
    52. }  

     以上的obtainFreshBeanFactory是很關(guān)鍵的一個(gè)方法,里面會(huì)調(diào)用loadBeanDefinition方法,如下:

    Java代碼  收藏代碼
    1. protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {  
    2.     // Create a new XmlBeanDefinitionReader for the given BeanFactory.  
    3.     XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);  
    4.   
    5.     // Configure the bean definition reader with this context's  
    6.     // resource loading environment.  
    7.     beanDefinitionReader.setResourceLoader(this);  
    8.     beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));  
    9.   
    10.     // Allow a subclass to provide custom initialization of the reader,  
    11.     // then proceed with actually loading the bean definitions.  
    12.     initBeanDefinitionReader(beanDefinitionReader);  
    13.     loadBeanDefinitions(beanDefinitionReader);  
    14. }  

     LoadBeanDifinition方法很關(guān)鍵,這里特定于整個(gè)IOC容器,實(shí)例化了一個(gè)XmlBeanDefinitionReader來解析Resource文件。關(guān)于Resource文件如何初始化和xml文件如何解析都在

    Java代碼  收藏代碼
    1. loadBeanDefinitions(beanDefinitionReader);  

     里面的層層調(diào)用完成,這里不在累述。

    小結(jié) 

    Spring的擴(kuò)展性是毋庸置疑的,學(xué)習(xí)spring的設(shè)計(jì)是一個(gè)很好的實(shí)踐理論結(jié)合。主要個(gè)人覺得有幾點(diǎn):

    1.  框架頂層的設(shè)計(jì)有著很好的抽象,遵循面向接口編程的規(guī)范。ResourceBeanFactoryApplicationContext都是非常好的接口抽象,非常明確的定義了該組件的一些功能。

    2.  利用組合模式。

    3.  個(gè)組件的實(shí)現(xiàn)里大量使用了模板方法模式,提升了同一組件代碼的復(fù)用性。

    4.  各種設(shè)計(jì)保留了擴(kuò)展的接口,很多基于spring的框架都可以很容易的介入實(shí)現(xiàn)了自己的一些擴(kuò)展。

    5.  框架里采用里很多經(jīng)典的設(shè)計(jì)模式,如代理、裝飾、策略等等。

    posted @ 2013-02-28 10:46 brock 閱讀(270) | 評(píng)論 (0)編輯 收藏

    先來看下一X經(jīng)典配置:

     

    /opt/taobao/java/bin/java -Dprogram.name=run.sh –server

     -Xms4g           //指定 jvm 的最小 heap 大小 (-Xms默認(rèn)是物理內(nèi)存的1/4)

     -Xmx4g           //指定 jvm 的最大 heap 大小

     -Xmn2g

     -Xss1m

     -XX:PermSize=96m

     -XX:MaxPermSize=256m

     -XX:SurvivorRatio=10

     -XX:+HeapDumpOnOutOfMemoryError    //

     -XX:HeapDumpPath=/home/admin/logs/java.hprof -verbose:gc -Xloggc:/home/admin/logs/gc.log

     -XX:+PrintGCDetails

     -XX:+PrintGCDateStamps

     -XX:+UseConcMarkSweepGC

     -XX:+UseCMSCompactAtFullCollection

     -XX:CMSInitiatingOccupancyFraction=80

     -XX:+UseCompressedOops

     -XX:+DisableExplicitGC

     -Djava.awt.headless=true

     -Dsun.net.client.defaultConnectTimeout=10000

     -Dsun.net.client.defaultReadTimeout=30000

     -Djava.net.preferIPv4Stack=true

     -Djava.endorsed.dirs=/opt/taobao/jboss/lib/endorsed

     -classpath /opt/taobao/jboss/bin/run.jar:/opt/taobao/java/lib/tools.jar org.jboss.Main -b 0.0.0.0 -Djboss.server.home.dir=/home/admin/purdecision/.default -Djboss.server.home.url=file:/home/admin/purdecision/.default

     

     

    這二年來這一堆東西我從來沒有懷疑過,“絕對(duì)正確完美”,據(jù)說是X寶的標(biāo)配。以至于從來沒有去分析了解過(一知半解),可能真的是惰性使然,也可能“忙”吧。無意中看到有人在博客里寫到 “溫故知新”,就像有人說讀think in java一樣每一回都有新的發(fā)現(xiàn)。下面就分析一下為什么要設(shè)置這些參數(shù),有何意義。

     

     

    上面參數(shù)說明:

    -Xmx4g :

     指定 jvm 的最大 heap 大小,默認(rèn)值為物理內(nèi)存的1/4,最佳設(shè)值應(yīng)該視物理內(nèi)存大小及計(jì)算機(jī)內(nèi)其他內(nèi)存開銷而定

     

    -Xms4g :

     指定 jvm 的最小 heap 大小。些值設(shè)置與-Xmx相同,以避免每次垃圾回收完成后JVM重新分配內(nèi)存

     

    -Xmn2g :

    設(shè)置年輕代大小為2G。整個(gè)堆大小=年輕代大小 + 年老代大小 + 持久代大小。持久代一般

    固定大小為64m,所以增大年輕代后,將會(huì)減小年老代大小。此值對(duì)系統(tǒng)性能影響較大,Sun官方推

    薦配置為整個(gè)堆的3/8(按此說應(yīng)設(shè)置為1.5G)

    -Xss1m

    每個(gè)線程堆棧大小為1M. 根據(jù)應(yīng)用的線程所需內(nèi)存大小進(jìn)行調(diào)整。在相同物理內(nèi)存下,減小這個(gè)值能生成更多的線程。(本機(jī)由于forest的原因-Xss2m,原因1:物理內(nèi)存過小 2window線程不能太多 猜的)

     

    -XX:PermSize=96m

    用于存放靜態(tài)文件,如今Java類、方法等。持久代對(duì)垃圾回收沒有顯著影響,但是有些應(yīng)用可能動(dòng)態(tài)生成或

    者調(diào)用一些class,例如Hibernate等,在這種時(shí)候需要設(shè)置一個(gè)比較大的持久代空間來存放這些運(yùn)行過程中新

    增的類。持久代大小通過-XX:MaxPermSize=<N>進(jìn)行設(shè)置

    -XX:PermSize=64MB
    最小尺寸,初始分配
    -XX:MaxPermSize=256MB
    最大允許分配尺寸,按需分配
    過小會(huì)導(dǎo)致:java.lang.OutOfMemoryError: PermGen space

    MaxPermSize
    缺省值和-server -client選項(xiàng)相關(guān)。
    -server
    選項(xiàng)下默認(rèn)MaxPermSize64m
    -client
    選項(xiàng)下默認(rèn)MaxPermSize32m

     

    (為什么不是64M 可能是webx設(shè)置的持久代空間比較多)

     

     

    -XX:SurvivorRatio=10

    SurvivorRatio=4設(shè)置年輕代中Eden區(qū)與Survivor區(qū)的大小比值。設(shè)置為4,則兩個(gè)Survivor

    區(qū)與一個(gè)Eden區(qū)的比值為2:4,一個(gè)Survivor區(qū)占整個(gè)年輕代的1/6

    這里設(shè)置為10也就是說一個(gè)Survivor區(qū)占整個(gè)年輕代的1/12,這個(gè)參數(shù)是否能小一點(diǎn),畢竟我們的應(yīng)用中沒有創(chuàng)建很大的對(duì)像。

     

     

    這個(gè)值設(shè)了有什么用?

    上面配置中-Xmn2g 年輕代大小,SurvivorRatio10時(shí) Eden超過1.66G時(shí)觸發(fā)minor gc(young generation)

    我的應(yīng)用gc 日志一直在young gc 就是如此,看來我的應(yīng)用 eden區(qū)還是設(shè)的很大的。

     


     -XX:+HeapDumpOnOutOfMemoryError

    參數(shù)表示當(dāng)JVM發(fā)生OOM時(shí),自動(dòng)生成DUMP文件。 

     

    -XX:HeapDumpPath=${目錄}參數(shù)表示生成DUMP文件的路徑,也可以指定文件名稱,例如:-XX:HeapDumpPath=${目錄}/java_heapdump.hprof。如果不指定文件名,默認(rèn)為:java_<pid>_<date>_<time>_heapDump.hprof

     

    -XX:+PrintGCDetails

    輸出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs] [GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured:

    112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs]

     

    -XX:+PrintGCTimeStamps -XX:+PrintGCPrintGCTimeStamps可與上面兩個(gè)混合使用

    輸出形式:11.851: [GC 98328K->93620K(130112K), 0.0082960 secs]

     

     

    -XX:+UseConcMarkSweepGC  

    設(shè)置并發(fā)收集器

     

    可以保證大部分工作都并發(fā)進(jìn)行(應(yīng)用不停止),垃圾回收只暫停很少的時(shí)間,此收集器適合對(duì)響應(yīng)時(shí)間要求

    比較高的中、大規(guī)模應(yīng)用。使用-XX:+UseConcMarkSweepGC打開。

    并發(fā)收集器主要減少年老代的暫停時(shí)間,他在應(yīng)用不停止的情況下使用獨(dú)立的垃圾回收線程,跟蹤可達(dá)對(duì)

    象。在每個(gè)年老代垃圾回收周期中,在收集初期并發(fā)收集器 會(huì)對(duì)整個(gè)應(yīng)用進(jìn)行簡短的暫停,在收集中還會(huì)再暫

    停一次。第二次暫停會(huì)比第一次稍長,在此過程中多個(gè)線程同時(shí)進(jìn)行垃圾回收工作。

     

    CMS采用的基礎(chǔ)算法是:標(biāo)記—清除 所有CMS不會(huì)整理、壓縮堆空間。這樣就會(huì)有一個(gè)問題:經(jīng)過CMS收集的堆會(huì)產(chǎn)生空間碎片

     

     

    -XX:CMSInitiatingOccupancyFraction=80

     

    啟動(dòng)并發(fā)收集器:因?yàn)椴l(fā)收集在應(yīng)用運(yùn)行時(shí)進(jìn)行收集,所以必須保證收集完成之前有足夠的內(nèi)存空間供程

    序使用,否則會(huì)出現(xiàn)“Concurrent Mode Failure”。通過設(shè)置-XX:CMSInitiatingOccupancyFraction=<N>

    指定還有多少剩余堆時(shí)開始執(zhí)行并發(fā)收集

     

    -XX:+UseCMSCompactAtFullCollection

    打開對(duì)年老代的壓縮。可能會(huì)影響性能,但是可以消除碎片

     

    XX:+UseCompressedOops

    通常64JVM消耗的內(nèi)存會(huì)比32位的大1.5倍,這是因?yàn)閷?duì)象指針在64位架構(gòu)下,長度會(huì)翻倍(更寬的尋址)。
    對(duì)于那些將要從32位平臺(tái)移植到64位的應(yīng)用來說,平白無辜多了1/2的內(nèi)存占用,這是開發(fā)者不愿意看到的。
    幸運(yùn)的是,從JDK 1.6 update14開始,64 bit JVM正式支持了 -XX:+UseCompressedOops 這個(gè)可以壓縮指針,起到節(jié)約內(nèi)存占用的新參數(shù)

     

    -XX:-DisableExplicitGC

    將會(huì)忽略手動(dòng)調(diào)用GC的代碼,如:System.gc(),將-DisableExplicitGC 改成+DisableExplicitGC即為啟用,默認(rèn)為啟用,什么也不寫,默認(rèn)是加號(hào),但是系統(tǒng)內(nèi)部默認(rèn)的并不是什么都啟用

     

     

    至此為什么Xmxxms 一樣,為什么用CMS(并發(fā)收集器),為什么用了cms 要使用-XX:+UseCMSCompactAtFullCollection,為什么用XX:+UseCompressedOops等等,相信大家和我一樣有所了解。不過對(duì)于有些還是不清楚理解有誤,可能還要來來回回?fù)v騰,不足之處請(qǐng)大家補(bǔ)充。

     

     

    posted @ 2013-02-27 14:25 brock 閱讀(1061) | 評(píng)論 (0)編輯 收藏

    1. 代理模式主要有兩種:靜態(tài)代理和動(dòng)態(tài)代理 

    2. 靜態(tài)代理: 

    比如要在輸出“HelloWorld”前打印一個(gè)字符串“Welcome” 

    A:先定義一個(gè)接口類 
    Java代碼  收藏代碼
    1. package ttitfly.proxy;      
    2.      
    3. public interface HelloWorld {      
    4.     public void print();      
    5. //  public void say();      
    6. }   
       



    B: 定義一個(gè)該接口的實(shí)現(xiàn)類 

    java 代碼 
    Java代碼  收藏代碼
    1. package ttitfly.proxy;      
    2.      
    3. public class HelloWorldImpl implements HelloWorld{      
    4.      
    5.     public void print(){      
    6.         System.out.println("HelloWorld");      
    7.     }      
    8. //  public void say(){      
    9. //      System.out.println("Say Hello!");      
    10. //  }      
    11. }      




    C:定義一個(gè)靜態(tài)代理類 
    Java代碼  收藏代碼
    1. package ttitfly.proxy;      
    2.      
    3. public class StaticProxy implements HelloWorld{      
    4.      
    5.     public HelloWorld helloWorld ;      
    6.     public StaticProxy(HelloWorld helloWorld){      
    7.         this.helloWorld = helloWorld;      
    8.     }      
    9.           
    10.     public void print(){      
    11.         System.out.println("Welcome");      
    12.         //相當(dāng)于回調(diào)      
    13.         helloWorld.print();      
    14.     }      
    15.           
    16. //  public void say(){      
    17. //      //相當(dāng)于回調(diào)      
    18. //      helloWorld.say();      
    19. //  }      
    20. }      




    D: 一個(gè)測(cè)試類: 
    Java代碼  收藏代碼
    1. package ttitfly.proxy;      
    2.      
    3. public class TestStaticProxy {      
    4.      
    5.     public static void main(String[] args){      
    6.         HelloWorld helloWorld = new HelloWorldImpl();      
    7.         StaticProxy staticProxy = new StaticProxy(helloWorld);      
    8.         staticProxy.print();      
    9.               
    10. //      staticProxy.say();      
    11.     }      
    12. }      


    可以看出靜態(tài)代理類有一個(gè)很不爽的缺點(diǎn):當(dāng)如果接口加一個(gè)方法(把上面所有的代碼的注釋給去掉),所有的實(shí)現(xiàn)類和代理類里都需要做個(gè)實(shí)現(xiàn)。這就增加了代碼的復(fù)雜度。動(dòng)態(tài)代理就可以避免這個(gè)缺點(diǎn)。 

    3 。動(dòng)態(tài)代理 

    動(dòng)態(tài)代理與普通的代理相比較,最大的好處是接口中聲明的所有方法都被轉(zhuǎn)移到一個(gè)集中的方法中處理(invoke),這樣,在接口方法數(shù)量比較多的時(shí)候,我們可以進(jìn)行靈活處理,而不需要像靜態(tài)代理那樣每一個(gè)方法進(jìn)行中轉(zhuǎn)。 

    動(dòng)態(tài)代理類只能代理接口,代理類都需要實(shí)現(xiàn)InvocationHandler類,實(shí)現(xiàn)invoke方法。該invoke方法就是調(diào)用被代理接口的所有方法時(shí)需要調(diào)用的,該invoke方法返回的值是被代理接口的一個(gè)實(shí)現(xiàn)類 

    代理類: 
    Java代碼  收藏代碼
    1. package ttitfly.proxy;          
    2.          
    3. import java.lang.reflect.InvocationHandler;          
    4. import java.lang.reflect.Method;          
    5. import java.lang.reflect.Proxy;          
    6. //動(dòng)態(tài)代理類只能代理接口,代理類都需要實(shí)現(xiàn)InvocationHandler類,實(shí)現(xiàn)invoke方法。該invoke方法就是調(diào)用被代理接口的所有方法時(shí)需要調(diào)用的,該invoke方法返回的值是被代理接口的一個(gè)實(shí)現(xiàn)類          
    7. public class DynamicProxy implements InvocationHandler{          
    8.               
    9.     private Object object;           
    10.     //綁定關(guān)系,也就是關(guān)聯(lián)到哪個(gè)接口(與具體的實(shí)現(xiàn)類綁定)的哪些方法將被調(diào)用時(shí),執(zhí)行invoke方法。      
    11.     //Proxy.newProxyInstance的第三個(gè)參數(shù)是表明這些被攔截的方法執(zhí)行時(shí)需要執(zhí)行哪個(gè)InvocationHandler的invoke方法      
    12.     public Object bindRelation(Object object){           
    13.         this.object = object;          
    14.         return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(),this);           
    15.     }           
    16.     //攔截關(guān)聯(lián)的這個(gè)實(shí)現(xiàn)類的方法被調(diào)用時(shí)將被執(zhí)行          
    17.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {           
    18.         System.out.println("Welcome");          
    19.         Object result = method.invoke(object, args);           
    20.         return result;          
    21.     }          
    22.          
    23. }          


    測(cè)試類: 
    Java代碼  收藏代碼
    1. package ttitfly.proxy;          
    2.          
    3. public class TestDynamicProxy {          
    4.     public static void main(String[] args){          
    5.         HelloWorld helloWorld = new HelloWorldImpl();          
    6.         DynamicProxy dp = new DynamicProxy();          
    7.         //在這里綁定的是HelloWorld,也就是HelloWorld是被代理接口。所以綁定關(guān)系時(shí),需要傳遞一個(gè)HelloWorld的實(shí)現(xiàn)類的實(shí)例化對(duì)象。          
    8.         HelloWorld helloWorld1 = (HelloWorld)dp.bindRelation(helloWorld);           
    9.         helloWorld1.print();           
    10.         helloWorld1.say();          
    11.               
    12.         //helloWorld2將不被攔截      
    13.         HelloWorld helloWorld2 = new HelloWorldImpl();      
    14.         helloWorld2.print();           
    15.         helloWorld2.say();      
    16.               
    17.     }          
    18. }          



    在測(cè)試類里調(diào)用實(shí)現(xiàn)類的print和say方法,因?yàn)榇眍惱锎砹薍elloWorld的所有方法。所以就不需要像靜態(tài)代理類那樣一一實(shí)現(xiàn)了。 
    posted @ 2013-02-21 12:01 brock| 編輯 收藏

         摘要: 序列化運(yùn)行時(shí)使用一個(gè)稱為 serialVersionUID 的版本號(hào)與每個(gè)可序列化類相關(guān)聯(lián),該序列號(hào)在反序列化過程中用于驗(yàn)證序列化對(duì)象的發(fā)送者和接收者是否為該對(duì)象加載了與序列化兼容的類。如果接收者加載的該對(duì)象的類的 serialVersionUID 與對(duì)應(yīng)的發(fā)送者的類的版本號(hào)不同,則反序列化將會(huì)導(dǎo)致 InvalidClassException。可序列化類可以通過聲明名為 "serialVer...  閱讀全文
    posted @ 2013-02-21 11:41 brock| 編輯 收藏

         摘要: 泛型是Java SE 5.0中引入的一項(xiàng)特征,自從這項(xiàng)語言特征出現(xiàn)多年來,我相信,幾乎所有的Java程序員不僅聽說過,而且使用過它。關(guān)于Java泛型的教程,免費(fèi)的,不免費(fèi)的,有很多。我遇到的最好的教材有:The Java TutorialJava Generics and Collections, by Maurice Naftalin and Philip WadlerEffective Jav...  閱讀全文
    posted @ 2013-02-21 11:31 brock| 編輯 收藏

    僅列出標(biāo)題
    共15頁: 上一頁 1 2 3 4 5 6 7 8 9 下一頁 Last 
    主站蜘蛛池模板: 亚洲日韩激情无码一区| 中国亚洲女人69内射少妇| 麻豆安全免费网址入口| 久久久久亚洲av毛片大| 98精品全国免费观看视频| 亚洲人成色777777精品| 久久亚洲国产中v天仙www| 四虎成人免费观看在线网址| 色婷婷综合缴情综免费观看| 日韩电影免费在线观看中文字幕| 亚洲国产精品无码久久久| 日本v片免费一区二区三区| 国产免费久久久久久无码| 亚洲国产人成在线观看| 中文字幕不卡亚洲| 性做久久久久免费观看| 精品免费久久久久久久| 永久免费AV无码网站国产| 大片免费观看92在线视频线视频| 亚洲AV无码久久久久网站蜜桃| 久久精品亚洲视频| 精品国产_亚洲人成在线高清| 日韩视频免费一区二区三区| 中文字幕亚洲免费无线观看日本 | 夜夜嘿视频免费看| 7723日本高清完整版免费| 国产高清不卡免费视频| 青柠影视在线观看免费| aaa毛片免费观看| 一级做a爱过程免费视频高清| 亚洲国产成人久久精品软件| 亚洲午夜无码毛片av久久京东热| 亚洲一本综合久久| 亚洲专区先锋影音| 亚洲成在人线电影天堂色| 亚洲国产成人手机在线电影bd| 亚洲国产精品线观看不卡| 2020天堂在线亚洲精品专区| 亚洲精品无码mⅴ在线观看| 成人婷婷网色偷偷亚洲男人的天堂| 羞羞视频免费观看|