Spring?IOC中對象的創(chuàng)建、策略及銷毀時機(jī)和生命周期詳解
一、對象的創(chuàng)建方式
Spring會幫助我們創(chuàng)建bean,那么它底層是調(diào)用什么方法進(jìn)行創(chuàng)建的呢?有以下三種方法
- 使用構(gòu)造方法
- 使用工廠類方法
- 使用工廠類的靜態(tài)方法
接下來詳細(xì)講解這三種方法。
1. 使用構(gòu)造方法
Spring默認(rèn)使用類的空參構(gòu)造方法創(chuàng)建bean,假如類沒有空參構(gòu)造方法,將無法完成bean的創(chuàng)建,接下來我們可以測試一下。
package com.example.dao; import com.example.pojo.Student; public class StudentDaoImpl1 implements StudentDao{ /*public StudentDaoImpl1() { }*/ public StudentDaoImpl1(int a){}; @Override public Student findById(int id){ return new Student(id,"程序員","北京"); } }
錯誤原因:Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'studentDao' defined in class path resource [bean.xml]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'int' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
翻譯:上下文初始化過程中遇到異常-取消刷新嘗試:org.springframework.beans.factory.UnsatisfiedDependencyException:創(chuàng)建類路徑資源[bean.xml]中定義的名稱為“studentDao”的bean時出錯:通過構(gòu)造函數(shù)參數(shù)0表示的不滿足依賴關(guān)系;嵌套異常為org.springframework.beans.factory.NoSuchBeanDefinitionException:沒有可用的類型為“int”的符合條件的bean:應(yīng)至少有1個符合自動連線候選條件的bean。依賴項注釋:{}
其實就是沒有空的構(gòu)造函數(shù),加上一個就好了
2. 使用工廠類方法
Spring可以調(diào)用工廠類的方法創(chuàng)建bean:創(chuàng)建工廠類,工廠類提供創(chuàng)建對象的方法,在配置文件中配置創(chuàng)建bean的方式為工廠方式。
工廠類StudentDaoFactory:
package com.example.dao; public class StudentDaoFactory { public StudentDao getStudentDao(){ return new StudentDaoImpl1(1); } }
bean.xml的配置:
<!-- id: 工廠對象的id,class:工廠類 --> <bean id="studentDaoFactory" class="com.example.dao.StudentDaoFactory" /> <!-- id:bean對象的id,factory-bean:工廠對象的id,factory-method:工廠方法 --> <bean id="studentDao" factory-bean="studentDaoFactory" factory-method="getStudentDao"></bean>
測試方法:
@Test public void t2(){ // 創(chuàng)建spring容器 ApplicationContext ac = new FileSystemXmlApplicationContext("C:\\JavaProjects\\06SSM_Projects\\springdemo\\spring_ioc1\\src\\main\\resources\\bean.xml"); // 從容器中獲取對象 StudentDao userDao = ac.getBean("studentDao",StudentDao.class); System.out.println(userDao); System.out.println(userDao.findById(1));; }
測試結(jié)果:
OK,確實成功寫出來了
3. 使用工廠類的靜態(tài)方法
Spring可以調(diào)用工廠類的靜態(tài)方法創(chuàng)建bean,創(chuàng)建工廠類,工廠提供創(chuàng)建對象的靜態(tài)方法,在配置文件中配置創(chuàng)建bean的方式為工廠靜態(tài)方法。
工廠類StudentDaoFactory2
package com.example.dao; public class StudentDaoFactory2 { public static StudentDao getStudentDao2() { return new StudentDaoImpl2(); } }
bean.xml的配置
<!-- id:bean的id class:工廠全類名 factory-method:工廠靜態(tài)方法 --> <bean id="studentDao" class="com.example.dao.StudentDaoFactory2" factory-method="getStudentDao2"/>
都是可以成功運行的。
二、對象的創(chuàng)建策略
scope屬性設(shè)置對象的創(chuàng)建策略。
Spring通過配置 <bean> 中的 scope 屬性設(shè)置對象的創(chuàng)建策略,共有兩種種創(chuàng)建策略。
1. 單例策略
singleton:單例,默認(rèn)策略。整個項目只會創(chuàng)建一個對象,通過 <bean> 中的 lazy-init 屬性可以設(shè)置單例對象的創(chuàng)建時機(jī):lazy-init="false"(默認(rèn)):立即創(chuàng)建,在容器啟動時會創(chuàng)建配置文件中的所有Bean對象。lazy-init="true":延遲創(chuàng)建,第一次使用Bean對象時才會創(chuàng)建。下面測試獲取對象后的哈希值是否一樣就可以知道是否配置單例策略了
bean.xml的配置
<bean id="studentDao" class="com.example.dao.StudentDaoImpl2" scope="singleton" lazy-init="true" />
測試方法
@Test public void t3(){ // 創(chuàng)建Spring容器 ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); // 從容器獲取對象 StudentDao studentDao1 = ac.getBean("studentDao",StudentDao.class); StudentDao studentDao2 = ac.getBean("studentDao",StudentDao.class); StudentDao studentDao3 = ac.getBean("studentDao",StudentDao.class); System.out.println(studentDao1.hashCode()); System.out.println(studentDao2.hashCode()); System.out.println(studentDao3.hashCode()); }
運行結(jié)果
OK,得到的對象都是同一個哈希值,說明確實是同一個對象也就是說成功配置了單例模式。
2. 多例策略
prototype:多例,每次從容器中獲取時都會創(chuàng)建對象。
bean.xml配置
<!-- 配置多例策略 --> <bean id="studentDao" class="com.itbaizhan.dao.StudentDaoImpl2" scope="prototype"></bean>
測試結(jié)果
得到的哈希值不一樣,說明得到的是不同的對象,確實是多例策略。
- request:每次請求創(chuàng)建一個對象,只在web環(huán)境有效。
- session:每次會話創(chuàng)建一個對象,只在web環(huán)境有效。
- gloabal-session:一次集群環(huán)境的會話創(chuàng)建一個對象,只在web環(huán)境有效。
三、對象的銷毀時機(jī)
對象的創(chuàng)建策略不同,銷毀時機(jī)也不同:
- singleton:對象隨著容器的銷毀而銷毀。
- prototype:使用JAVA垃圾回收機(jī)制銷毀對象。
- request:當(dāng)處理請求結(jié)束,bean實例將被銷毀。
- session:當(dāng)HTTP Session最終被廢棄的時候,bean也會被銷毀掉。
- gloabal-session:集群環(huán)境下的session銷毀,bean實例也將被銷毀。
四、生命周期方法
Bean對象的生命周期包含創(chuàng)建——使用——銷毀,Spring可以配置Bean對象在創(chuàng)建和銷毀時自動執(zhí)行的方法:
1. 定義生命周期方法
在StudentDaoImpl2中新增生命周期方法
// 創(chuàng)建時自動執(zhí)行的方法 public void init(){ System.out.println("使用StudentDaoImpl2創(chuàng)建對象"+this.hashCode()); } // 銷毀時自動執(zhí)行的方法 public void destroy(){ System.out.println("銷毀StudentDaoImpl2創(chuàng)建的對象"+this.hashCode()); }
2. 配置生命周期方法
<!-- init-method:創(chuàng)建對象時執(zhí)行的方法 destroy-method:銷毀對象時執(zhí)行的方法 --> <bean id="studentDao" class="com.itbaizhan.dao.StudentDaoImpl2" scope="singleton" init-method="init" destroy-method="destory"></bean>
3. 測試
測試方法
@Test public void t3(){ // 創(chuàng)建Spring容器 ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean1.xml"); // 銷毀Spring容器,ClassPathXmlApplicationContext才有銷毀容器的方法 ac.close(); }
測試結(jié)果
也確實可以
五、獲取Bean對象的方式
1. 通過id/name獲取
獲取對象的時候是這樣:
StudentDao studentDao = (StudentDao) ac.getBean("studentDao");
2. 通過類型獲取
獲取對象的時候是這樣:
StudentDao studentDao2 = ac.getBean(StudentDao.class);
不需要進(jìn)行類型強(qiáng)轉(zhuǎn)
3. 通過類型+id/name獲取
雖然使用類型獲取不需要強(qiáng)轉(zhuǎn),但如果在容器中有一個接口的多個實現(xiàn)類對象,則獲取時會報錯,此時需要使用類型+id/name獲取,獲取對象是這樣:
StudentDao studentDao2 = ac.getBean("studentDao",StudentDao.class);
到此這篇關(guān)于Spring IOC中對象的創(chuàng)建、策略及銷毀時機(jī)和生命周期詳解的文章就介紹到這了,更多相關(guān)Spring IOC對象策略及生命周期內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot導(dǎo)出Excel的四種實現(xiàn)方式
近期接到了一個小需求,要將系統(tǒng)中的數(shù)據(jù)導(dǎo)出為Excel,且能將Excel數(shù)據(jù)導(dǎo)入到系統(tǒng),對于大多數(shù)研發(fā)人員來說,這算是一個最基本的操作了,本文就給大家總結(jié)一下SpringBoot導(dǎo)出Excel的四種實現(xiàn)方式,需要的朋友可以參考下2024-01-01Spring Cloud 中@FeignClient注解中的contextId屬性詳解
這篇文章主要介紹了Spring Cloud 中@FeignClient注解中的contextId屬性詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09Spring Boot 整合 Shiro+Thymeleaf過程解析
這篇文章主要介紹了Spring Boot 整合 Shiro+Thymeleaf過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-10-10Apache DolphinScheduler實現(xiàn)自動化打包單機(jī)/集群部署詳解
這篇文章主要為大家介紹了Apache DolphinScheduler實現(xiàn)自動化打包單機(jī)/集群部署詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09簡單了解redis常見客戶端及Sharding機(jī)制原理
這篇文章主要介紹了簡單了解redis常見客戶端及Sharding機(jī)制原理,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-09-09