Rising Sun

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

          #

          http://sunnylocus.iteye.com/blog/342996
             大多數(shù)程序員都知道Servlet的生命周期,簡(jiǎn)單的概括這就分為四步:servlet類加載--->實(shí)例化--->服務(wù)--->銷毀。對(duì)這個(gè)過(guò)程只是膚淺了解下,對(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ù)來(lái)調(diào)用Servlet對(duì)象的init方法。

          2、在Servlet容器啟動(dòng)后:客戶首次向Servlet發(fā)出請(qǐng)求,Servlet容器會(huì)判斷內(nèi)存中是否存在指定的Servlet對(duì)象,如果沒(méi)有則創(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方法來(lái)釋放資源。以上所講的就是Servlet對(duì)象的生命周期。那么Servlet容器如何知道創(chuàng)建哪一個(gè)Servlet對(duì)象?

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

          我們來(lái)看一下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:客戶訪問(wèn)的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é)信息來(lái)決定創(chuàng)建Servlet對(duì)象的順序,如果此配置節(jié)信息為負(fù)數(shù)或者沒(méi)有配置,那么在Servlet容器啟動(dòng)時(shí),將不加載此Servlet對(duì)象。當(dāng)客戶訪問(wèn)Servlet容器時(shí),Servlet容器根據(jù)客戶訪問(wèn)的URL地址,通過(guò)<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)上打印提示語(yǔ)句,不過(guò)我發(fā)現(xiàn)在tomcat中,只要不停止web容器,servlet是不會(huì)被銷毀的。有沒(méi)有什么方法,當(dāng)service方法執(zhí)行完畢就銷毀這個(gè)servlet呢,我問(wèn)了下老師,他說(shuō)寫一個(gè)監(jiān)聽(tīng)器,不過(guò)我不知道怎么去實(shí)現(xiàn)它,如果有朋友知道實(shí)現(xiàn)的過(guò)程,還請(qǐng)賜教。

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


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

          posted @ 2013-03-05 10:59 brock 閱讀(229) | 評(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 閱讀(323) | 評(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 閱讀(215) | 評(píng)論 (0)編輯 收藏

               摘要: http://singleant.iteye.com/blog/1177358 接上文 啃啃老菜: Spring IOC核心源碼學(xué)習(xí)(一) ,本文將以 ClassPathXmlApplicationContext 這個(gè)容器的實(shí)現(xiàn)作為基礎(chǔ),學(xué)習(xí)容器的初始化過(guò)程。ClassPathXmlApplicationContext 類體系結(jié)構(gòu)以下是&...  閱讀全文
          posted @ 2013-02-28 11:04 brock 閱讀(826) | 評(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è)視角來(lái)考慮:

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

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

          可以用xmlproperties文件等語(yǔ)義化配置文件表示。

          描述對(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ì)不同的配置文件語(yǔ)法,采用不同的解析器。

           

          基于以上問(wèn)題,對(duì)應(yīng)過(guò)來(lái),剛好是 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ì)某一種特定資源的訪問(wèn)策略。它是spring資源訪問(wèn)策略的一個(gè)基礎(chǔ)實(shí)現(xiàn),應(yīng)用在很多場(chǎng)景。

           

           

           

           

          具體可以參考文章:

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

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

           

           

          2.BeanDefinition

          用來(lái)抽象和描述一個(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用來(lái)讀取xml描述配置的bean對(duì)象。



           

          4.BeanFactory

          用來(lái)定義一個(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

          從名字來(lái)看叫應(yīng)用上下文,是和應(yīng)用環(huán)境息息相關(guān)的。沒(méi)錯(cuò)這個(gè)就是我們平時(shí)開(kāi)發(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è)過(guò)程的封裝自然就需要ApplicationContextApplicationContext和應(yīng)用環(huán)境細(xì)細(xì)相關(guān),常見(jiàn)實(shí)現(xiàn)有ClasspathXmlApplicationContext,FileSystemXmlApplicationContext,WebApplicationContext等。ClasspathxmlFileSystemWeb等詞都代表了應(yīng)用和環(huán)境相關(guān)的一些意思,從字面上不難理解各自代表的含義。

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

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

          2.  支持不同的信息源。

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

          ……



           

           

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

           

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

           


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

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

          以下是Refresh的基本步驟:
          1.把配置xml文件轉(zhuǎn)換成resource。resource的轉(zhuǎn)換是先通過(guò)ResourcePatternResolver來(lái)解析可識(shí)別格式的配置文件的路徑
          (如"classpath*:"等),如果沒(méi)有指定格式,默認(rèn)會(huì)按照類路徑的資源來(lái)處理。 
          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來(lái)實(shí)例化一個(gè)bean。當(dāng)然根據(jù)bean的lazy-init、protetype等屬性設(shè)置不同以上過(guò)程略有差別。

           

          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來(lái)解析Resource文件。關(guān)于Resource文件如何初始化和xml文件如何解析都在

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

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

          小結(jié) 

          Spring的擴(kuò)展性是毋庸置疑的,學(xué)習(xí)spring的設(shè)計(jì)是一個(gè)很好的實(shí)踐理論結(jié)合。主要個(gè)人覺(jué)得有幾點(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 閱讀(273) | 評(píng)論 (0)編輯 收藏

          先來(lái)看下一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

           

           

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

           

           

          上面參數(shù)說(shuō)明:

          -Xmx4g :

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

           

          -Xms4g :

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

           

          -Xmn2g :

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

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

          薦配置為整個(gè)堆的3/8(按此說(shuō)應(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)存過(guò)小 2window線程不能太多 猜的)

           

          -XX:PermSize=96m

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

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

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

          -XX:PermSize=64MB
          最小尺寸,初始分配
          -XX:MaxPermSize=256MB
          最大允許分配尺寸,按需分配
          過(guò)小會(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也就是說(shuō)一個(gè)Survivor區(qū)占整個(gè)年輕代的1/12,這個(gè)參數(shù)是否能小一點(diǎn),畢竟我們的應(yīng)用中沒(méi)有創(chuàng)建很大的對(duì)像。

           

           

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

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

          我的應(yīng)用gc 日志一直在young gc 就是如此,看來(lái)我的應(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打開(kāi)。

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

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

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

           

          CMS采用的基礎(chǔ)算法是:標(biāo)記—清除 所有CMS不會(huì)整理、壓縮堆空間。這樣就會(huì)有一個(gè)問(wèn)題:經(jīng)過(guò)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”。通過(guò)設(shè)置-XX:CMSInitiatingOccupancyFraction=<N>

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

           

          -XX:+UseCMSCompactAtFullCollection

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

           

          XX:+UseCompressedOops

          通常64JVM消耗的內(nèi)存會(huì)比32位的大1.5倍,這是因?yàn)閷?duì)象指針在64位架構(gòu)下,長(zhǎng)度會(huì)翻倍(更寬的尋址)。
          對(duì)于那些將要從32位平臺(tái)移植到64位的應(yīng)用來(lái)說(shuō),平白無(wú)辜多了1/2的內(nèi)存占用,這是開(kāi)發(fā)者不愿意看到的。
          幸運(yùn)的是,從JDK 1.6 update14開(kāi)始,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等等,相信大家和我一樣有所了解。不過(guò)對(duì)于有些還是不清楚理解有誤,可能還要來(lái)來(lái)回回?fù)v騰,不足之處請(qǐng)大家補(bǔ)充。

           

           

          posted @ 2013-02-27 14:25 brock 閱讀(1064) | 評(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)在反序列化過(guò)程中用于驗(yàn)證序列化對(duì)象的發(fā)送者和接收者是否為該對(duì)象加載了與序列化兼容的類。如果接收者加載的該對(duì)象的類的 serialVersionUID 與對(duì)應(yīng)的發(fā)送者的類的版本號(hào)不同,則反序列化將會(huì)導(dǎo)致 InvalidClassException。可序列化類可以通過(guò)聲明名為 "serialVer...  閱讀全文
          posted @ 2013-02-21 11:41 brock| 編輯 收藏

               摘要: 泛型是Java SE 5.0中引入的一項(xiàng)特征,自從這項(xiàng)語(yǔ)言特征出現(xiàn)多年來(lái),我相信,幾乎所有的Java程序員不僅聽(tīng)說(shuō)過(guò),而且使用過(guò)它。關(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頁(yè): 上一頁(yè) 1 2 3 4 5 6 7 8 9 下一頁(yè) Last 
          主站蜘蛛池模板: 宣化县| 陇南市| 安吉县| 吴旗县| 来凤县| 江永县| 喀什市| 泸水县| 天镇县| 墨竹工卡县| 星子县| 绍兴县| 芦溪县| 桦川县| 奇台县| 唐山市| 黄山市| 崇明县| 琼中| 正定县| 玉门市| 盈江县| 洛宁县| 福安市| 河北省| 获嘉县| 上高县| 大安市| 石景山区| 乡城县| 福建省| 巴中市| 冀州市| 无锡市| 沐川县| 富顺县| 泸西县| 甘谷县| 开鲁县| 浮山县| 西藏|