Java?Spring中Bean的作用域及生命周期
1.Bean的作用域
1.1 被修改的Bean案例

原因:Bean的作用域默認是單例模式的,也就是說所有?的使?的都是同?個對象!之前我們學單例模式的時候都知道,使?單例可以很?程度上提?性能,所以在 Spring 中Bean 的作?域默認也是 singleton 單例模式。
@Component
public class Users {
@Bean
public User user1(){
User user = new User();
user.setId(1);
user.setName("Java");
return user;
}
}@Component
public class Bean1 {
@Autowired
private User user;
public User getUser(){
System.out.println("Bean1對象未修改name之前 : "+user);
user.setName("C++");
return user;
}
}@Component
public class Bean2 {
@Autowired
private User user;
public User getUser(){
return user;
}
}public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
Bean1 bean1 = context.getBean("bean1",Bean1.class);
System.out.println(bean1.getUser());
Bean2 bean2 = context.getBean("bean2",Bean2.class);
System.out.println(bean2.getUser());
}
}1.2 為什么使用單例模式作為默認作用域
- 相同資源只創(chuàng)建一份,節(jié)省空間
- 不需要過多的創(chuàng)建和銷毀對象,執(zhí)行速度提高
1.3 作用域
作用域,一般理解為:限定程序中變量的可?范圍叫做作?域,或者說在源代碼中定義變量的某個區(qū)域就叫做作?域。
?Bea的作?域是指Bean在 Spring整個框架中的某種?為模式,?如singleton單例作?域,就表
示Bean在整個Spring中只有?份,它是全局共享的,那么當其他?修改了這個值之后,那么另?個
?讀取到的就是被修改的值。
在Spring中,bean 的作用域被稱為是行為模式,因為在Spring看來,單例模式,就是一種行為,意味著在整個Spring中bean只能存在一份。
1.4 Bean的6種作用域
- singleton:單例作?域
- prototype:原型作?域(多例作?域)
- request:請求作?域
- session:會話作?域
- application:全局作?域
- websocket:HTTP WebSocket 作?域
后四種都是SpringMVC中限定使用的,因此現(xiàn)階段我們只學前兩個就行。
1.5 設(shè)置作用域
回到剛才的案例,Bean2希望獲取到的bean對象是未被修改的,我們就可以將單例模式修改為多例模式。
使用@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)


使用@Scope("prototype")

2.Spring執(zhí)行流程和Bean的生命周期

ps:當執(zhí)行性到裝配Bean的屬性那一步時,當掃描到有屬性注入時,會先停下類注入,優(yōu)先進行屬性注入,因為后面的方法可能會用到該屬性。
2.1 Bean的生命周期
所謂的生命周期指的是一個對象從誕生到銷毀的整個生命過程,我們把這個過程就叫做一個對象的生命周期。
Bean 的生命周期分為以下5大部分:
- 1.實例化 Bean(為 Bean 分配內(nèi)存空間)
- 2.設(shè)置屬性(Bean 注入和裝配)
- 3.Bean 初始化
實現(xiàn)了各種 Aware 通知的方法,如 BeanNameAware、BeanFactoryAware、 ApplicationContextAware 的接口方法,例如:Spring在初始化 bean,是需要給 bean 賦予 id(name)。而設(shè)置 beanName 成功的話,就會生成一個 beadNameAware 通知;執(zhí)行 BeanPostProcessor 初始化前置方法(如果沒有重寫此方法,按照源碼操作);執(zhí)行 @PostConstruct 初始化方法,依賴注入操作之后被 執(zhí)行;執(zhí)行自己指定的 init-method 方法(如果有指定的話),是Spring中bean標簽內(nèi)指定的方法;

這個初始化方法和上面一個用注解初始化的方法是兩個不同時期的產(chǎn)物,init是xml時代產(chǎn)物,@PostConstruct是注解時代產(chǎn)物。優(yōu)先級:當梁總方法同時存在時,優(yōu)先執(zhí)行注解,再執(zhí)行init執(zhí)行 BeanPostProcessor 初始化后置方法(如果沒有重寫此方法,按照源碼操作)。
- 4.使用 Bean
- 5.銷毀 Bean銷毀容器的各種方法, 如 @PreDestroy、DisposableBean 接口方法、destroy-method。
@PreDestroy和destroy-method的關(guān)系和初始化方法的兩個關(guān)系差不多
優(yōu)先級:@ProDestroy > 重寫的DisposableBean接口方法 > destroy-method
執(zhí)行流程圖如下:

ps:實例化和初始化的區(qū)別:實例化就是 分配內(nèi)存空間。初始化,就是把我們一些參數(shù),方法的具體實現(xiàn)邏輯給加載進去。
2.1.1生命周期演示


xml配置如下:

Bean
public class BeanLifeComponent implements BeanNameAware {
@PostConstruct
public void PostConstruct(){
System.out.println("執(zhí)行@PostConstruct");
}
public void init(){
System.out.println("執(zhí)行bean-init-method");
}
public void use(){
System.out.println("正在使用bean");
}
@PreDestroy
public void PreDestroy(){
System.out.println("執(zhí)行@PreDestroy");
}
public void setBeanName(String s){
System.out.println("執(zhí)行了Aware通知");
}
}啟動類
public class App2 {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
BeanLifeComponent beanLifeComponent = context.getBean(BeanLifeComponent.class);
beanLifeComponent.use();
context.destroy();
}
}xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:content="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<content:component-scan base-package="com.beans"></content:component-scan>
<bean id="1" class="com.beans.BeanLifeComponent" init-method="init"></bean>
</beans>2.1.2 為什么要先設(shè)置屬性,在進行初始化
@Controller
public class TestUser {
@Autowired
private Test test;
public TestUser(){
test.sayHi();
System.out.println("TestUser->調(diào)用構(gòu)造方法");
}
}如果這段代碼先執(zhí)行了初始化,也就是其構(gòu)造方法,會用到test對象,此時還沒有設(shè)置屬性,test就為null,會造成空指針異常。因此必須先設(shè)置屬性,在進行初始化。
到此這篇關(guān)于Java Spring中Bean的作用域及生命周期的文章就介紹到這了,更多相關(guān)Java Spring Bean 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java如何實現(xiàn)讀取txt文件內(nèi)容并生成Word文檔
本文主要介紹了通過Java實現(xiàn)讀取txt文件中的內(nèi)容,并將內(nèi)容生成Word文檔。文章的代碼非常詳細,具有一定的學習價值,感興趣的小伙伴可以了解一下2021-12-12
win10 下 idea2020安裝 JetBrains-agent.jar 包后閃退的問題及解決辦法
這篇文章主要介紹了win10 下 idea2020安裝 JetBrains-agent.jar 包后閃退的解決辦法,本文給大家?guī)碓蚍治黾敖鉀Q方法,需要的朋友可以參考下2020-08-08
SpringBoot + Shiro前后端分離權(quán)限
這篇文章主要為大家詳細介紹了SpringBoot + Shiro前后端分離權(quán)限,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-12-12

