javascript
Bean的作用域和生命周期-----Spring
1.之前學(xué)過的變量的作用域:是指變量在方法中或者作用域中的某種行為,現(xiàn)在我們來進(jìn)行了解一下Bean的作用域
咱們的Java中的公共類稱之為Bean或者是JavaBean,Spring對(duì)象中的生命周期指的是交給SpringIOC容器的對(duì)象,所以說咱們的Spring Bean對(duì)象在進(jìn)行使用的時(shí)候,無需通過new來進(jìn)行創(chuàng)建對(duì)象,只需要通過依賴注入,從Spring要取出適用的對(duì)象即可
Bean的作用域在Spring容器里面默認(rèn)是單例模式,是為了節(jié)省資源,并且沒有過多的生命周期的創(chuàng)建和銷毀,如果說每一次注入都創(chuàng)建一個(gè)新的User對(duì)象,系統(tǒng)的開銷就會(huì)更大的
1)什么是作用域:限定程序中變量的可用范圍就叫做作用域,或者在源代碼中定義變量的某個(gè)區(qū)域就叫做作用域,有幾種類型;
2?)但是Bean的作用域是指Bean在整個(gè)Spring框架容器里面的某種行為模式(重要),?是Bean的類型有哪些 ,比如說singLeton單例作用域,就表示Bean在整個(gè)Spring框架里面只有一份,他是全局共享的,那么當(dāng)其他人修改了這個(gè)值之后,那么另一個(gè)人讀到的就是被修改的值
3)Spring容器在進(jìn)行初始化一個(gè)Bean的實(shí)例的時(shí)候,同時(shí)會(huì)指定該實(shí)例的作用域,Spring有六種作用域,最后四種是針對(duì)SpringMVC生效的
因?yàn)閱卫J街槐怀跏蓟淮?#xff0c;初始化一次之后我們可以反復(fù)的進(jìn)行使用,所以使用的性能比較高,所有人都是用的一個(gè)對(duì)象;
1.Bean的6種作用域:注意后四種是SpringMVC里面的作用范圍,是基于SpringMVC來進(jìn)行生效的,但是普通的Spring項(xiàng)目(非web項(xiàng)目,普通的JAVA項(xiàng)目,SpringCore)只有前兩種;也就說明Bean在Spring里面一共有六種類型;
web項(xiàng)目:通過瀏覽器或者postman的方式來進(jìn)行訪問一個(gè)地址的方式來進(jìn)行發(fā)送Http請(qǐng)求,與咱們的在idea中的Spring代碼進(jìn)行交互,是具有上面的5種值;
1.singleton:單例模式
描述:該作用域下的Bean在IOC容器中只存在一個(gè)實(shí)例:
當(dāng)我們進(jìn)行獲取Bean(即通過applicationContext.getBean等方法獲取以及裝配Bean(即通過Autowired注入)這都是一個(gè)對(duì)象;
場(chǎng)景:通常無狀態(tài)的Bean的使用該作用域,無狀態(tài)表示Bean對(duì)象的屬性不需要進(jìn)行更新,不會(huì)修改Bean,通常我們的Spring默認(rèn)選擇該作用域;
缺點(diǎn):一個(gè)改變了,其他的就都改變了;
2.prototype:原型模式-----多例模式
描述:每次對(duì)于該作用域(每一次注入)下面的每一次Bean的請(qǐng)求都會(huì)創(chuàng)建新的實(shí)例:
1)當(dāng)我們進(jìn)行獲取Bean的時(shí)候(即通過applicationContext.getBean()方法來進(jìn)行獲取Bean對(duì)象的時(shí)候)或者裝配Bean(即通過Autowired或者@Resource來進(jìn)行注入)都會(huì)創(chuàng)建出新的對(duì)象實(shí)例,針對(duì)有狀態(tài)的Bean作用該作用域
2)這幾種方法獲取的都是新的對(duì)象實(shí)例,每一個(gè)類中引入的對(duì)象都是自己的;
場(chǎng)景:通常有狀態(tài)的Bean使用該作用域
3.Request
描述:針對(duì)每一次HTTP請(qǐng)求都會(huì)創(chuàng)建新的Bean實(shí)例,就類似于prototype,不管是一次會(huì)話還是兩次會(huì)話,每進(jìn)行訪問一次,都會(huì)重新給一個(gè)新的對(duì)象,就是一次HTTP請(qǐng)求和響應(yīng)的共享Bean
場(chǎng)景:一次http請(qǐng)求和響應(yīng)的共享Bean
備注:只限于SpringMVC中使用,在咱們的普通項(xiàng)目是不能進(jìn)行使用的
4.session
描述:在一個(gè)HttpSession中,定義一個(gè)Bean實(shí)例,一個(gè)會(huì)話共享一個(gè)Bean
場(chǎng)景:用戶會(huì)話的共享Bean,比如說記錄一個(gè)用戶的登錄信息,是針對(duì)一個(gè)人來進(jìn)行操作的,只要是這個(gè)人操作的,就會(huì)對(duì)應(yīng)到這個(gè)實(shí)例,比如說張三進(jìn)行登錄了,那么在張三進(jìn)行登錄的過程中,使用的都是同一個(gè)對(duì)象;
備注:只是限于SpringMVC中進(jìn)行使用
5.application
描述:在一個(gè)http servlet context中對(duì)應(yīng)一個(gè)Bean實(shí)例
場(chǎng)景:Application 的作用范圍在服務(wù)器一開始執(zhí)行服務(wù),到服務(wù)器關(guān)閉為止。 Application 相比于Session、request和page的范圍最大、停留的時(shí)間也最久。
存入application的信息在Web應(yīng)用程序運(yùn)行期間,所有的頁面都可以訪問這個(gè)信息。
備注:只限于SpringMVC進(jìn)行使用
singletion是作用于整個(gè)Spring(IOC容器)容器當(dāng)中,application是在一個(gè)Servlet容器當(dāng)中(處理WEB請(qǐng)求)
6.WebSocket------網(wǎng)頁聊天
描述:在一個(gè)Http WebSocket的生命周期中,定義一個(gè)Bean實(shí)例
場(chǎng)景:WebSocket的每一次對(duì)話
備注:限定在Spring WebSocket中使用,WebSocket的每一次對(duì)話里面,保存了一個(gè)Map結(jié)構(gòu)的頭信息,將用來包裹對(duì)象頭,第一次初始化之后,直到這一次WebSocket結(jié)束之后用到的都是同一個(gè)Bean;
單例作用域和全局作用域
singletion是Spring Core的作用域,application是Spring Web的作用域(只有在Servlet里面,在SpringMVC里面才有效果的)
singletion是作用域IOC的容器,而application是作用于Servlet的容器
我們?nèi)绾芜M(jìn)行設(shè)置Bean的作用域呢?保證多例的作用域
1)直接使用@Scope他是可以即應(yīng)用于類注解上面,又能應(yīng)用于方法注解上面
2)Scope翻譯成中文是作用域的意思,雖然說@Scope是可以進(jìn)行應(yīng)用到類注解和方法注解,但是如果應(yīng)用到類注解,就說明進(jìn)行設(shè)置當(dāng)前這個(gè)類所生效;
3)我們一定要注意,我們?nèi)绻胍椒ǖ姆祷刂凳菃卫幕蛘呤嵌嗬?#xff0c;我們就可以經(jīng)這個(gè)注解修飾方法,如果我們要使用的是@Bean注解·+@Scope,@Scope一定要放在方法上進(jìn)行注解,不能放在類上;
4)我們可以直接設(shè)置作用域的具體的值通過@Scope("propotype")
5)我們還可以根據(jù)ConfigurableBeanFactory和WebApplicationContext提供的Scope_XXX變量來進(jìn)行設(shè)置,我們可以把這個(gè)變量放在@Scope里面
@Component public class GetBean {@Bean(name ="u1")//將當(dāng)前User對(duì)象存儲(chǔ)到Spring里面@Scope("prototype")public User GetUser1(){User user=new User();user.setId(1);user.setName("李佳偉");return user;}2.Bean的大的執(zhí)行流程-----重要----Spring生命周期
1)啟動(dòng)Spring容器-----執(zhí)行main方法(執(zhí)行帶有ApplicationContext的main方法,并指定了配置文件)
2)加載Spring配置文件(配置一個(gè)組件的掃描路徑,通常在resource,web.xml里面或者是使用<Beans>標(biāo)簽)
3)將Bean對(duì)象注冊(cè)到Spring容器里面:加載配置文件中的bean或者根據(jù)配置文件中的bean組件的根掃描路徑,進(jìn)行對(duì)Bean對(duì)象的掃描(會(huì)進(jìn)行掃描五大類注解,那么就會(huì)把這五大注解修飾過的類或者是當(dāng)前加了五大注解的類里面加了@Bean注解的方法返回的類存儲(chǔ)到Spring容器里面)
出現(xiàn)了屬性注入:(如果說我們?cè)贏類里面注入了B類,那么先會(huì)把B類給注入到Spring容器里面,在進(jìn)行A類注冊(cè)到Spring里面)-------先去裝配Bean的屬性,再去裝配Bean
4)將加載的對(duì)象存入到Spring容器里面,進(jìn)行加載
5)其他需要使用Bean對(duì)象的地方就可以直接進(jìn)行獲取并使用了
6)執(zhí)行完之后所有業(yè)務(wù)之后,執(zhí)行銷毀操作
Bean的執(zhí)行流程(Spring的執(zhí)行流程)-----啟動(dòng)Spring容器-----實(shí)例化Bean(分配內(nèi)存空間,從無到有)-----將Bean進(jìn)行注冊(cè)到Spring里面(存儲(chǔ)操作)-----我們最后再將Bean裝配到需要的類中,取操作;
Bean的生命周期-----重要:是指Bean在整個(gè)IOC容器中從創(chuàng)建到銷毀的整個(gè)過程
所謂的Bean的生命周期是指Bean在整個(gè)Spring容器里面,也就是在IOC容器里面從創(chuàng)建到銷毀的整個(gè)過程
因?yàn)镾pringBoot是基于Spring來進(jìn)行創(chuàng)建的,所以Bean在整個(gè)Spring和SpringBoot的行為都是一樣的
1)實(shí)例化Bean,為Bean對(duì)象整體分配內(nèi)存空間-----把二進(jìn)制的字節(jié)碼轉(zhuǎn)化成一個(gè)類對(duì)象
2)進(jìn)行設(shè)置它的屬性(進(jìn)行Bean的注入和裝配)
我們一定是要先進(jìn)行加載屬性的,如果先進(jìn)行初始化方法,很有可能就會(huì)在方法里面用到這個(gè)類屬性(如果這個(gè)屬性被@Resource或者Autowired所修飾,那么我們就需要對(duì)使用的Bean進(jìn)行初始化注入),一個(gè)類是有屬性和方法的
3)(Bean初始化,一系列準(zhǔn)備工作的統(tǒng)稱),執(zhí)行各種通知方法,比如說在飛機(jī)上進(jìn)行檢查工作,檢查按鈕;
3.1)實(shí)現(xiàn)了各種Aware通知的方法,創(chuàng)建一個(gè)類,實(shí)現(xiàn)了BeanNameAware,BeanFactoryAware,還有ApplicationContext接口的方法
3.2)執(zhí)行實(shí)現(xiàn)BeanPostProcessor接口初始化前置方法
3.3)執(zhí)行帶注解的@PostConstruct修飾的初始化方法,依賴注入操作之后執(zhí)行
3.4)執(zhí)行自己所指定的init-method方法,如果有指定的話(最早使用XML的方式,在沒有注解之前)---也是初始化方法
3.5)執(zhí)行實(shí)現(xiàn)了BeanPostProcess接口初始化后置方法
4)使用Bean
5)進(jìn)行銷毀Bean
5.1首先會(huì)執(zhí)行@PreDestory這是銷毀前置方法,比如說像記錄一下時(shí)間,日志
5.2如果說實(shí)現(xiàn)了DisposableBean接口方法
5.3destory-method:銷毀前的執(zhí)行方法,在XML里面進(jìn)行設(shè)置
初始化前置方法和初始化后置方法是給所有Bean進(jìn)行服務(wù)的,這些方法不能寫在某一個(gè)Bean中,否則不會(huì)執(zhí)行
如果有的話,就執(zhí)行(前提是你得重寫了前置方法他才會(huì)執(zhí)行)
下面我們寫了一些代碼來進(jìn)行演示:
@Controller public class BeanStart implements BeanNameAware {@Overridepublic void setBeanName(String s) {System.out.println("執(zhí)行通知方法"+s);}@PostConstruct//出生于注解時(shí)代public void start(){System.out.println("執(zhí)行被注解@PostConstruct修飾的方法");}public void init()//直接這么寫,是無法進(jìn)行執(zhí)行的,我們必須要在XML里面進(jìn)行相應(yīng)的配置,這里面的方法名字是可以隨便取的,只要和XML里面的名字相匹配就可以了{(lán)System.out.println("執(zhí)行init方法");}public void destory(){System.out.println("執(zhí)行destory方法");}@PreDestroypublic void predestory(){System.out.println("執(zhí)行被注解修飾的");} } class HelloServlet{public static void main(String[] args) {ApplicationContext context=new ClassPathXmlApplicationContext("web.xml");UserController userController=context.getBean("beanStart",BeanStart.class);userController.destory();} } web.xml配置文件: <beans><bean id="userController" class="APP.Controller.UserController" init-method="init(方法名)" destroy-method="destory"></bean> </beans> 打印結(jié)果:執(zhí)行通知方法userController 執(zhí)行被注解@PostConstruct修飾的方法 執(zhí)行通知方法userinit 執(zhí)行被注解@PostConstruct修飾的方法 執(zhí)行init方法 執(zhí)行destory方法可不可以先執(zhí)行初始化方法,在進(jìn)行設(shè)置屬性?
假設(shè)現(xiàn)在@Controller里面進(jìn)行屬性注入了UserService,先進(jìn)行初始化操作,就會(huì)出現(xiàn)空指針異常,所以要先進(jìn)行屬性注入,在進(jìn)行初始化
咱們的初始化前置方法和后置方法是為所有的Bean來進(jìn)行服務(wù)的,而不是給某一個(gè)Bean來進(jìn)行服務(wù)的,這一系列的方法不可以寫在某一個(gè)具體的Bean里面,否則不會(huì)執(zhí)行
總結(jié)
以上是生活随笔為你收集整理的Bean的作用域和生命周期-----Spring的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 360wifi在linux系统如何使用,
- 下一篇: SpringMVC---(2)