spring單例如何改多例
spring單例改多例
單例:就像你一生只有一個老婆。也就是對象始終是同一個。
多例:就像你一生有好多個老婆。也就是對象每次都是新的。
spring默認是單例模式(就每個請求都是用的同一對象,對于dao層肯定是棒棒的),但是有的時候,我們需要每個請求都
產(chǎn)生一個新的對象,就如做微信小程序,用scoket、不可能一直都用一個來接收的,因為需要分配房間,所以需要使用到多例。
對于struts2來說,action必須用多例,因為action本身含有請求參數(shù)的值,即可改變的狀態(tài);
而對于STRUTS1來說,action則可用單例,因為請求參數(shù)的值是放在actionForm中,而非action中的;
配置某個類為多例:
<bean id="user" class="modle.User" scope="prototype"> ?</bean>
但是比如service配置的是多例、dao又是單例,那肯定不行了,因為不能自動注入。
所以需要獲得一個新的dao實例,但是手動new的都不可以,那么就借助通過實現(xiàn) BeanFactoryAware 接口來獲得factory
附加自己待測試
public class userService implements BeanFactoryAware{ ?? ? private UserDao userDao; ? private BeanFactory factory; ? public void userService (){ ? ? this.userDao= (UserDao)factory.getBean("userDao"); ? ? userDao.work(); ? } ? public UserDao getUserDao() { ? ? ? ? return userDao; ? } public void setBeanFactory(BeanFactory f) throws BeansException { ? ? factory = f; ? } ? }
spring單例、多例使用方法
今天聊聊單例和多例。只想看spring管理的實例有哪些模式,直接看最后。
相信大部分使用java 做web開發(fā)的開發(fā)人員都用過spring。spring功能最基礎(chǔ)功能就是IoC(Inversion of control——控制反轉(zhuǎn))、AOP(Aspect Oriented Programming——面向切面編程)。其中IoC核心是DI(Dependency injection——依賴注入)。
我們最開始寫項目自然而然的是沒有框架,生寫!但代碼多了之后,發(fā)現(xiàn)有很多代碼,可以抽成公共方法。有些又可以抽成一個類。而有些類又是貫穿整個項目生命周期始終的,而且往往這些類的初始化方法很復(fù)雜且重要。那怎么辦,總不能每次使用的時候初始化一遍吧,這樣很耗編碼時間不說,還很占用計算機性能。于是,工廠模式應(yīng)運而生。通過工廠模式獲取各個重要的實例對象。這樣就帶來一個問題,怎樣保證實例只創(chuàng)建一次呢?單例模式應(yīng)運而生。于是,我們常用的框架spring就成了。
然而需求的發(fā)展往往不是單一技術(shù)能很好解決的。單例、依賴注入固然好。但是也讓我們的開發(fā)模式陷入一種定式。即controller、service、dao這樣雖然是快速規(guī)范的劃分,但是往往一些復(fù)雜的邏輯只在service或者controller中寫會有大量的私有方法、或者一個方法幾百上千行。整個業(yè)務(wù)操作的生命周期局限在一個方法內(nèi)。并不能好好利用面向?qū)ο蟮乃枷?,寫到最后完全就是面向過程編程。一旦邏輯復(fù)雜,那方法寫的簡直慘不忍睹,而且局限于方法的生命周期,很多參數(shù)可能會多次調(diào)用數(shù)據(jù)庫查同一個數(shù)據(jù)。那么有什么辦法能改變這個局面呢?歷史總會給我們答案。
自新世紀之初提出“領(lǐng)域驅(qū)動設(shè)計”(DDD)以來,這玩意一直不受重視,不僅玄之又玄的理論很少有人去專研,而且所謂“敏捷開發(fā)”的盛行,也不適合DDD。但這里并不介紹DDD,說一說DDD的充血模型要在傳統(tǒng)數(shù)據(jù)驅(qū)動的業(yè)務(wù)中使用將面臨的首要問題——單例如何注入進充血模型。
比如,我有個User對象,而對象的保存查詢操作是與數(shù)據(jù)庫操作。我并不想讓User是一個干癟的值對象,而是讓他具備行為,是一個真正有血有肉的充血模型。那么saveUser(User)這樣的方法就不再由Dao提供,而是應(yīng)該由user.save()替代。熟悉JPA的同學(xué)肯定想到了。jpa支持對象操作替代傳統(tǒng)的repository操作。例如典型的user中的List<Role> roles屬性作為關(guān)聯(lián)查詢的屬性。如果設(shè)置級聯(lián)查詢?yōu)閼屑虞d,那么jpa只在調(diào)用user.getRoles()方法執(zhí)行的時候發(fā)送sql查詢對應(yīng)的role。這是因為jpa代理了user實體對象,而且這也有個問題。如果被jpa代理的對象調(diào)用toString()方法,獲取roles屬性打印時會觸發(fā)jpa操作。但這時可能已經(jīng)不屬于jpa Entity的生命周期了。踩過坑的朋友肯定遇到過打印日志報了莫名的jpa異常,百思不得其解吧。
況且我們想要的不只是這些。我們可能有些其他的被sqring單例管理的對象方法需要在不同的實例對象中使用。例如:user想要發(fā)送數(shù)據(jù)到遠程。那么user.send()可就不歸jpa管了。此時如果要想讓user能做這個事情必然只能通過spring上下文獲取被spring管理的類。聰明的小伙肯定想到了。我讓user也被spring管理起來,不就可以注入了嗎?是的,但是一旦被spring管理默認就是單例的??偛荒苊總€user都是同一個吧。其實spring可以設(shè)置多例的,只是用的人很少。在加有@componet之類注解(@service、@bean...等)受spring管理的類上再加上注解@scope(“prototype”)那么被spring管理的類就是多例的。稍微麻煩點的是,要想獲取多例必須通過spring上下文獲取。如果直接注入,那么注入的user還是只是那一個。相信各位一定都看過@scope(“prototype”)這種寫法吧。但spring其實提供了常量,@scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE),常量可以防止寫錯那長串單詞。有了多例,我們有血有肉的User對象寫起來就方便了許多。
為什么我們要這么做呢?“把權(quán)力關(guān)進籠子”,這句話在編程界就是強類型、常量、枚舉這些來體現(xiàn)的。同樣,DDD也是把權(quán)力鎖進領(lǐng)域?qū)ο?。避免隨心所欲的service、隨心所欲的repository導(dǎo)致代碼后期維護成為爬“屎山”。
spring支持的模式
1.ConfigurableBeanFactory.SCOPE_SINGLETON
——單例
2.ConfigurableBeanFactory.SCOPE_PROTOTYPE
——多例
擴展模式
3.WebApplicationContext.SCOPE_APPLICATION
4.WebApplicationContext.SCOPE_GLOBAL_SESSION
5.WebApplicationContext.SCOPE_SESSION
6.WebApplicationContext.SOCPE_REQUEST
以上擴展模式看名字都能明白不做多介紹了。希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Elasticsearch?mapping?概念及自動創(chuàng)建示例
這篇文章主要為大家介紹了Elasticsearch?mapping?概念及自動創(chuàng)建示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-11-11Java+MySql圖片數(shù)據(jù)保存與讀取的具體實例
之前一直沒有做過涉及到圖片存儲的應(yīng)用,最近要做的東東涉及到了這個點,就做了一個小的例子算是對圖片存儲的初試吧2013-06-06java實現(xiàn)解析json復(fù)雜數(shù)據(jù)的方法詳解
這篇文章主要為大家詳細介紹了java如何實現(xiàn)解析json復(fù)雜數(shù)據(jù),文中的示例代碼講解詳細,具有一定的借鑒價值,感興趣的小伙伴可以學(xué)習一下2024-01-01