轉--解決Spring中singleton的Bean依賴於prototype的Bean的問題
原文連結:https://my.oschina.net/itblog/blog/205860
scope="prototype"沒寫的問題,專案中對一個表的增刪該操作是用一個action,這個actionadd,update,delete,save這些方法, 新增和修改是共用一個頁面,當頁面得到id時代表進行的修改操作,反之是新增操作。因為在配置spring的bean是忘了寫scope="prototype" 所以每次新增時都顯示最後一次訪問過的記錄,scope="prototype" 會在該型別的物件被請求 時建立一個新的action物件。如果沒有配置scope=prototype則新增的時候不會新建一個action,他任然會保留上次訪問的過記錄的資訊
webwork的Action不是執行緒安全的,要求在多執行緒環境下必須是一個執行緒對應一個獨立的例項,不能使用singleton。所以,我們在Spring配置Webwork Action Bean時,需要加上屬性scope=”prototype”或singleton=”false”。
singleton模式指的是對某個物件的完全共享,包括程式碼空間和資料空間,說白了,如果一個類是singleton的,假如這個類有成員變數,那麼這個成員變數的值是各個執行緒共享的(有點類似於static的樣子了),當執行緒A往給變數賦了一個值以後,執行緒B就能讀出這個值。因此,對於前臺Action,肯定不能使用singleton的模式,必須是一個執行緒請求對應一個獨立的例項。推而廣之,只要是帶資料成員變數的類,為了防止多個執行緒混用資料,就不能使用singleton。對於我們用到的Service、Dao,之所以用了singleton,就是因為他們沒有用到資料成員變數,如果誰的Service需要資料成員變數,請設定singleton=false。
有狀態的bean都使用Prototype作用域,而對無狀態的bean則應該使用singleton作用域。
另外,當Spring容器中作用域不同的Bean相互依賴時,可能出現一些問題,例如:一個作用域為Singleton的Bean(設為A)依賴於一個作用域為prototype的Bean(設為B)。由於A是單例的,只有一次初始化的機會,它的依賴關係也只在初始化階段被設定,但它所依賴的B每次都會建立一個全新的例項,這將使A中的B不能及時得到更新。這樣將導致如果客戶端多次請求A,並呼叫A中B的某個方法(或獲取A中B的某個屬性),服務端總是返回同一個B,但客戶端直接請求B卻能獲得最新的物件,這就產生了物件不同步的情況。這樣就違背了B初衷:本來希望B具有prototype的行為,但是卻表現出singleton的行為了。那麼,問題如何解決呢?
辦法有二:
-
部分放棄依賴注入:當A每次需要B時,主動向容器請求新的Bean例項,即可保證每次注入的B都是最新的例項。
-
利用方法注入。
第一種方式顯然不是一個好的做法,程式碼主動請求Bean例項,必然導致程式碼與SpringAPI耦合在一起,造成嚴重的程式碼汙染。通常情況下,我們會採用第二種做法。使用方法注入。
方法注入通常使用lookup方法注入,利用lookup方法注入可以讓Spring容器重寫容器中Bean的抽象或具體方法,返回查詢容器中其他Bean的結果,被查詢的Bean通常是一個non-singleton的Bean(儘管也可以是一個singleton的Bean)。Spring通過使用CGLIB庫修改客戶端的二進位制碼,從而實現上述要求。看下面的例子:
public abstract class Developer implements Person {
public Developer() {
System.out.println("Spring例項化主調的Bean...Developer例項");
}
//定義一個抽象方法,該方法將由Spring實現
public abstract Phone getPhone();
@Override
public void call() {
System.out.println("正在使用 " + getPhone() + " 打電話");
System.out.println(getPhone().call());
}
}
上面的CellPhone將被部署成prototype的Bean,並被一個singleton的Bean所依賴。如果讓Spring容器直接將prototype的Bean注入到singleton中,就會出現上面的問題。為了解決這個問題,我們在singleton的Bean裡增加一個抽象方法,該方法的返回型別是一個被依賴的Bean——注意這個方法是一個抽象方法,因為程式中沒有為該方法提供實現,這個實現過程由Spring完成。下面是該singleton作用域的Bean的程式碼:
public abstract class Developer implements Person {
public Developer() {
System.out.println("Spring例項化主調的Bean...Developer例項");
}
//定義一個抽象方法,該方法將由Spring實現
public abstract Phone getPhone();
@Override
public void call() {
System.out.println("正在使用 " + getPhone() + " 打電話");
System.out.println(getPhone().call());
}
}
上面的程式碼定義了一個抽象的getPhone方法,通常情況下,程式不能呼叫這個方法,但Spring框架將會負責為該方法提供是先提,這樣這個方法就會變成具體方法了,程式也就可以呼叫該方法了。為了讓Spring知道如何實現該方法,我們需要在配置檔案中使用<lookup-method>標籤,這個標籤需要指定如下兩個屬性:
-
name:指定需要讓Spring實現的方法
-
bean:指定Spring實現該方法後返回的值
下面是配置片段:
<!-- 將CellPhone部署成prototype的範圍 -->
<bean id="cellPhone" class="com.abc.CellPhone" scope="prototype" />
<bean id="developer" class="com.abc.Developer">
<!-- getPhone方法返回CellPhone,每次呼叫將獲取新的CellPhone -->
<lookup-method name="getPhone" bean="cellPhone" />
</bean>
上面配置的<lookup-method>指定Spring將負責實現getPhone方法,該方法將返回容器中的prototype型別的cellPhone例項。下面是測試類:
public class Test {
public static void main(String args[]) {
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
Developer d = context.getBean("developer", Developer.class);
d.call();
d.call();
}
}
執行結果如下:
Spring例項化主調的Bean...Developer例項
Spring例項化依賴的Bean...CellPhone例項
正在使用 [email protected] 打電話
Spring例項化依賴的Bean...CellPhone例項
正在打電話...
Spring例項化依賴的Bean...CellPhone例項
正在使用 [email protected] 打電話
Spring例項化依賴的Bean...CellPhone例項
正在打電話...
結果表明:當lookup方法注入後,系統每次呼叫getPhone都會返回最新的CellPhone例項而非最早的CellPhone例項。
注意:要保證lookup方法注入每次產生的Bean例項,必須將目標Bean(本例為cellPhone)佈署成prototype作用域。否則,如果容器中只有一個目標Bean例項,即使採用lookup方法注入,每次依然返回同一個Bean例項。另外,lookup方法注入不僅能用於設值注入,還能用於構造注入。
相關推薦
轉--解決Spring中singleton的Bean依賴於prototype的Bean的問題
原文連結:https://my.oschina.net/itblog/blog/205860 scope="prototype"沒寫的問題,專案中對一個表的增刪該操作是用一個action,這個actionadd,update,delete,save這些方法, 新增和修改是共
【轉】spring中對控制反轉和依賴注入的理解
由於最近沒有太多時間,不能深入的瞭解控制反轉和依賴注入,只好把別人的理解轉載過來,非常痛恨市面上各種教程對所謂的術語張口就來,等自己有了時間一定要寫出新手都能看懂的教程。 首先想說說IoC(Inversion of Control,控制反轉)。這是spring的核心,貫穿始終。所謂IoC
spring中的依賴檢查
ram 5.x 集合類型 name style 基本類 all cep 檢查 4個依賴檢查支持的模式: none – 沒有依賴檢查,這是默認的模式。 simple – 如果基本類型(int, long,double…)和集合類型(map, list..)的任何屬性都沒有設
解決Spring中使用context:component-scan命名空間配置錯誤
num lex odi exceptio type oca ted pac instance ** nested exception is org.xml.sax.SAXParseException; lineNumber: 16; columnNumber: 74; cv
轉:Spring中 @Autowired標籤與 @Resource標籤 的區別
Spring不但支援自己定義的@Autowired註解,還支援由JSR-250規範定義的幾個註解,如:@Resource、 @PostConstruct及@PreDestroy。 1. @Autowired @Autowired是Spring 提供的,需匯入  
深入理解Spring核心技術---Spring中的依賴注入
在前面的幾篇部落格中給大家介紹了Spring中的IOC容器,現在大家應該都知道IOC容器的概念和實現的原理了吧,IOC容器是Spring的核心,他的功能就是幫助開發者去儲存物件以及管理物件之間的關係。不用讓開發者自己去管理物件之間的關係,使開發者只需要專注於
如何解決spring中同一個類裡面方法之間呼叫的時候註解失效的問題
參考部落格:https://blog.csdn.net/z55887/article/details/81073450 @RestController public class Test { @Autowired ApplicationContext context;
論Spring中迴圈依賴的正確性與Bean注入的順序關係
一、前言 最近在做專案時候遇到一個奇葩問題,就是bean依賴注入的正確性與bean直接注入的順序有關係,但是正常情況下明明是和順序沒關係的啊,究竟啥情況那,不急,讓我一一道來。 二、普通Bean迴圈依賴-與注入順序無關 2.1 迴圈依賴例子與原理 public class BeanA {
解決Spring中Quart無法自動注入Bean問題
因專案需求,之前專案中已經有定時器的例子了,但是需求那邊過來的需求之前用的定時器並不能滿足,之前的定時器是用spring裡面的@Scheduled(cron = "0 0 0 * * ? ")這種方式,這是一種死的定時器,需求要的是動態定時器,使用者新增一個
解決spring中不同配置檔案中存在name或者id相同的bean可能引起的問題
spring對同一配置檔案中相同id或者name的兩個或以上的bean時,做直接拋異常的處理,而對不同配置檔案中相同id或者名稱的bean,只會在列印日誌級別為info的資訊,資訊內容大概為"Overriding bean definition for bean xxx :
Java日誌框架——JCL(Log4J,Java Logging API)轉SLF4J過程中重複依賴衝突問題
如文章《Java日誌框架——JCL(Log4J,Java Logging API)轉SLF4J》所述,在完成”JCL(Log4J,Java Logging API)轉SLF4J“的過程中,要注意重複依賴衝突問題。 比如一個專案原本使用JCL日誌框架(可以是具有對"commo
Spring中各種依賴注入的程式碼實現
DI:Spring稱之為依賴注入,就是維護物件和物件之間的關係 通俗的講,就是 給類的成員賦值。 1、屬性賦值: class A{ String str = “Hello Word !” } 注入: <bean id="A" class="類A
【轉】Spring 中配置sessionFactory及用法(JAVA後端)
編輯 刪除 Spring 中配置sessionFactory及用法 方法一: 1、在Spring的applicationContext.xml中配置bean <!-- 啟用註解注入 --> <context:annota
Spring中的依賴查詢和依賴注入
作者:[Grey](https://www.cnblogs.com/greyzeng/) 原文地址: [語雀](https://www.yuque.com/greyzeng/mnc4mc/oshvxb) [部落格園](https://www.cnblogs.com/greyzeng/p/14459565
[轉]使用@Test 也可以從spring容器中獲取依賴註入
oca fig article ring1 detail ice 如果 text resource 轉自:http://blog.csdn.net/u010987379/article/details/52091790 @RunWith(SpringJUnit4Cla
Spring Bean中迴圈依賴解決方案
在迴圈依賴是指在A中引用B,B中引用C,而C中引用A,容器建立物件時會出現死迴圈。相關解決方案如下: 1 選擇其一使其延遲載入,然後從上下文中獲取AService型別的bean即可。 現有AService 和BService,都在對方bean中注入,導致初始化時迴圈初始報錯,解決方案就是
Spring中-IOC-Bean的初始化-循環依賴的解決
creation reference single 填充 hash 可能 target get 完美 前言 在實際工作中,經常由於設計不佳或者各種因素,導致類之間相互依賴。這些類可能單獨使用時不會出問題,但是在使用Spring進行管理的時候可能就會拋出BeanCurren
Spring中的IOC(控制反轉)與DI(依賴注入)理解由淺入深-適用於小白
IOC(Inversion of Control )與 DI(Dependency injection)是sping的主要思想,不是技術! IOC控制反轉:一般我們在一個類中呼叫其它的類(非靜態類),需要新建一個該類的例項或者從其他途徑獲取該類的例項,然後對通過該例項進行操
《轉》maven中import scope依賴方式解決單繼承問題的理解
在maven多模組專案中,為了保持模組間依賴的統一,常規做法是在parent model中,使用dependencyManagement預定義所有模組需要用到的dependency(依賴) <dependencyManagement>
Spring中的迴圈依賴解決詳解
前言 說起Spring中迴圈依賴的解決辦法,相信很多園友們都或多或少的知道一些,但當真的要詳細說明的時候,可能又沒法一下將它講清楚。本文就試著儘自己所能,對此做出一個較詳細的解讀。另,需注意一點,下文中會出現類的例項化跟類的初始化兩個短語,為怕園友迷惑,