Springmvc 併發訪問的線程安全性問題

首先對於spring的IOC來講,對象是由Spring來幫咱們管理,也就是在Spring啓動的時候,在Spring容器中,由Spring給咱們建立的,Spring會幫咱們維護,通常都是單例的,也就是一個對象。html

 

spring生成對象默認是單例的。經過scope屬性能夠更改成多例。java

 

第一部分:驗證Spring生成對象默認是單例的。

 

下面咱們來一個網上的例子驗證一下:web

  1. <bean id="singleton" class="java.util.Date" scope="singleton"></bean>  
  2. <bean id="prototype" class="java.util.Date" scope="prototype"></bean>  
  1. package test;   
  2. import java.util.Date;  
  3. import org.springframework.context.ApplicationContext;  
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  5. import com.opensymphony.xwork2.ActionContext;  
  6.   
  7. public class TestScope {  
  8.   
  9.     public static void main(String[] args) {  
  10.   
  11.        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext-web.xml");  
  12.   
  13.        Date s1=(Date)context.getBean("singleton");  
  14.   
  15.        Date p1=(Date)context.getBean("prototype");  
  16.   
  17.        Date s2=(Date)context.getBean("singleton");  
  18.   
  19.        Date p2=(Date)context.getBean("prototype");  
  20.       
  21.        System.out.println("單例:"+(s1==s2));  
  22.   
  23.        System.out.println("非單例:"+(p1==p2));  
  24.   
  25.     }  
  26.   
  27.   
  28. }  


輸出結果:
ajax

結果spring

單例:true編程

非單例:false安全


注:複合數據類型的「== 」對比的是內存中存放的地址,因此此處咱們採用「==」去對比restful

由於object中的equals初始行爲是比較內存中的地址,但在一些類庫中被覆蓋掉了如(StringIntegerDate等)網絡

 

第二部分:SpringMVC和Struts2中是併發訪問否會存在線程安全問題。

 

對於使用過SpringMVC和Struts2的人來講,你們都知道SpringMVC是基於方法的攔截,而Struts2是基於類的攔截。架構

 

對於Struts2來講,由於每次處理一個請求,struts就會實例化一個對象;這樣就不會有線程安全的問題了;

而Spring的controller默認是Singleton的,這意味着每個request過來,系統都會用原有的instance去處理,這樣致使兩個結果:

一是咱們不用每次建立Controller,二是減小了對象建立和垃圾收集的時間;因爲只有一個Controller的instance,當多個線程調用它的時候,它裏面的instance變量就不是線程安全的了,會發生竄數據的問題。

 

固然大多數狀況下,咱們根本不須要考慮線程安全的問題,好比dao,service等,除非在bean中聲明瞭實例變量。所以,咱們在使用spring mvc 的contrller時,應避免在controller中定義實例變量。 
如:

 

  1. public class Controller extends AbstractCommandController {    
  2.     protected Company company;  
  3.     protected ModelAndView handle(HttpServletRequest request,HttpServletResponse response,Object command,BindException errors) throws Exception {  
  4.         company = ................;           
  5.      }             
  6.  }    


解決方案:

有幾種解決方法:
一、在Controller中使用ThreadLocal變量
二、在spring配置文件Controller中聲明 scope="prototype",每次都建立新的controller
所在在使用spring開發web 時要注意,默認Controller、Dao、Service都是單例的。

 

例如:

  1. @Controller  
  2. @RequestMapping("/fui")  
  3. public class FuiController extends SpringController {  
  4. //這麼定義的話就是單例  
  5.   
  6. @Controller  
  7. @Scope("prototype")  
  8. @RequestMapping("/fui")  
  9. public class FuiController extends SpringController {  
  10. //每次都建立  

 

第三部分:springMVC與struts2的區別。

 

下面是從網絡上摘抄的一段對比,你們能夠看看

點擊打開連接

 

1. 機制:spring mvc的入口是servlet,而struts2是filter,這樣就致使了兩者的機制不一樣。

 

2. 性能:spring會稍微比struts快。spring mvc是基於方法的設計,而sturts是基於類,每次發一次請求都會實例一個action,每一個action都會被注入屬性,而spring基於方法,粒度更細,但要當心把握像在servlet控制數據同樣。spring3 mvc是方法級別的攔截,攔截到方法後根據參數上的註解,把request數據注入進去,在spring3 mvc中,一個方法對應一個request上下文。而struts2框架是類級別的攔截,每次來了請求就建立一個Action,而後調用setter getter方法把request中的數據注入;struts2其實是經過setter getter方法與request打交道的;struts2中,一個Action對象對應一個request上下文。

 

3. 參數傳遞:struts是在接受參數的時候,能夠用屬性來接受參數,這就說明參數是讓多個方法共享的。


4. 設計思想上:struts更加符合oop的編程思想, spring就比較謹慎,在servlet上擴展。

 

5. intercepter的實現機制:struts有以本身的interceptor機制,spring mvc用的是獨立的AOP方式。這樣致使struts的配置文件量仍是比spring mvc大,雖然struts的配置能繼承,因此我以爲論使用上來說,spring mvc使用更加簡潔,開發效率Spring MVC確實比struts2高。spring mvc是方法級別的攔截,一個方法對應一個request上下文,而方法同時又跟一個url對應,因此說從架構自己上spring3 mvc就容易實現restful url。struts2是類級別的攔截,一個類對應一個request上下文;實現restful url要費勁,由於struts2 action的一個方法能夠對應一個url;而其類屬性卻被全部方法共享,這也就沒法用註解或其餘方式標識其所屬方法了。spring3 mvc的方法之間基本上獨立的,獨享request response數據,請求數據經過參數獲取,處理結果經過ModelMap交回給框架方法之間不共享變量,而struts2搞的就比較亂,雖然方法之間也是獨立的,但其全部Action變量是共享的,這不會影響程序運行,卻給咱們編碼,讀程序時帶來麻煩。

 

6. 另外,spring3 mvc的驗證也是一個亮點,支持JSR303,處理ajax的請求更是方便,只需一個註解@ResponseBody ,而後直接返回響應文本便可。

 

總結:

 

這樣也說明了SpringMVC還有Servlet都是方法的線程安全,因此在類方法聲明的私有或者公有變量不是線程安全的,而struts2的確實是線程安全的。

 

第四部分:那麼對於Struts2+Spring來管理注入的時候呢?


Struts2它是多實例的,對於每一個請求都會生成1個實例,spring默認是單實例的(下面針對Struts與Spring集成的兩種方式分別來介紹struts2和spring的兩種整合方式

一:對於無Spring插件(Struts2-spring-plugin-XXX.jar)的整合方式,須要在spring的action Bean中加業務邏輯控制器類配scope="prototype"。

 

  1. <bean id="user" class="modle.User" scope="prototype"></bean>  


:對於有Spring插件(Struts2-spring-plugin-XXX.jar)的整合方式:反編譯StrutsSpringObjectFactory以及相關的代碼才發現,若是在struts action的配置文件中<action name=".." class=".."/>中class寫的若是是完整的包名和類名的話就是struts建立action對象,也就是多實例的;

 

總結:若是是spring配置文件中的 bean的名字的話就是spring建立,那麼單實例仍是多實例就由spring的action Bean中的業務邏輯控制器類是否配置爲scope=」prototype」,有就是多實例的,沒有就是單實例的,順序是先從spring中找,找不到再從struts配置文件中找。

轉自 :http://blog.csdn.net/hejingyuan6/article/details/50363647

相關文章
相關標籤/搜索