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

