## 5.1、bean的作用域 ### 5.1.1、單例(預設且常用) #### 5.1.1.1、配置bean 
5.1.1.1、配置bean
註意:當bean不配置scope屬性時,預設是singleton(單例)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="student" class="org.rain.spring.pojo.Student"></bean>
</beans>
5.1.1.2、測試
由控制台日誌可知,此時ioc獲取到的兩個bean本質上是同一個對象
@Test
public void testScope() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-scope.xml");
Student student1 = applicationContext.getBean(Student.class);
Student student2 = applicationContext.getBean(Student.class);
System.out.println(student1 == student2);
}
5.1.2、多例
5.1.2.1、配置bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
scope屬性:設置bean的作用域
當屬性值為singleton時,在IOC容器中這個bean的對象始終為單實例;且創建對象的時機是IOC容器初始化時
當屬性值為prototype時,在IOC容器中這個bean的對象有多個實例;且創建對象的時機是獲取bean時
-->
<bean id="student" class="org.rain.spring.pojo.Student" scope="prototype"></bean>
</beans>
5.1.2.2、測試
由控制台日誌可知,此時ioc獲取到的兩個bean本質上是不同的對象
5.1.3、其他作用域
如果是在WebApplicationContext環境下還會有另外兩個作用域(但不常用):
-
request:在一個請求範圍內有效
-
session:在一個會話範圍內有效
5.2、bean的生命周期
5.2.1、創建User類
package org.rain.spring.pojo;
/**
* @author liaojy
* @date 2023/8/3 - 23:59
*/
public class User {
private Integer id;
private String username;
private String password;
private Integer age;
public User() {
System.out.println("生命周期1:創建對象");
}
public User(Integer id, String username, String password, Integer age) {
this.id = id;
this.username = username;
this.password = password;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
System.out.println("生命周期2:依賴註入");
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public void initMethod(){
System.out.println("生命周期3:初始化");
}
public void destroyMethod(){
System.out.println("生命周期4:銷毀");
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", age=" + age +
'}';
}
}
5.2.2、配置bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
init-method屬性:指定初始化方法
destroy-method屬性:指定銷毀方法
-->
<bean id="user" class="org.rain.spring.pojo.User" init-method="initMethod" destroy-method="destroyMethod">
<property name="id" value="1"></property>
<property name="username" value="張三"></property>
<property name="password" value="123"></property>
<property name="age" value="11"></property>
</bean>
</beans>
5.2.3、測試
@Test
public void testLifecycle(){
//ConfigurableApplicationContext是ApplicationContext子介面,擴展了刷新和關閉容器的方法
ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
User user = ioc.getBean(User.class);
System.out.println(user);
ioc.close();
}
5.3、作用域對生命周期的影響
5.3.1、作用域為單例時
5.3.1.1、配置bean
<bean id="user" class="org.rain.spring.pojo.User" init-method="initMethod" destroy-method="destroyMethod">
<property name="id" value="1"></property>
<property name="username" value="張三"></property>
<property name="password" value="123"></property>
<property name="age" value="11"></property>
</bean>
5.3.1.2、測試
由控制台日誌可知,當bean的作用域為單例時,生命周期的前三個步驟會在獲取IOC容器時執行
@Test
public void testLifecycle(){
//ConfigurableApplicationContext是ApplicationContext子介面,擴展了刷新和關閉容器的方法
ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
}
5.3.2、作用域為多例時
5.3.2.1、配置bean
<bean id="user" class="org.rain.spring.pojo.User" init-method="initMethod" destroy-method="destroyMethod" scope="prototype">
<property name="id" value="1"></property>
<property name="username" value="張三"></property>
<property name="password" value="123"></property>
<property name="age" value="11"></property>
</bean>
5.3.2.2、測試
由控制台日誌可知,當bean的作用域為多例時,生命周期的前三個步驟會在獲取bean時執行
@Test
public void testLifecycle(){
//ConfigurableApplicationContext是ApplicationContext子介面,擴展了刷新和關閉容器的方法
ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
User user = ioc.getBean(User.class);
}
5.4、bean的後置處理器
5.4.1、創建bean的後置處理器
註意:自定義的bean後置處理器,需要實現BeanPostProcessor介面
package org.rain.spring.process;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* @author liaojy
* @date 2023/8/4 - 23:52
*/
public class MyBeanProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanProcessor-->後置處理器postProcessBeforeInitialization");
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanProcessor-->後置處理器postProcessAfterInitialization");
return bean;
}
}
5.4.2、配置bean的後置處理器
註意:bean後置處理器不是單獨針對某一個bean生效,而是針對IOC容器中所有bean都會執行
<!-- bean的後置處理器要放入IOC容器才能生效 -->
<bean id="myBeanPostProcessor" class="org.rain.spring.process.MyBeanProcessor"></bean>
5.4.3、測試
由控制台日誌可知,bean的後置處理器會在生命周期的初始化前後添加額外的操作
@Test
public void testLifecycle(){
//ConfigurableApplicationContext是ApplicationContext子介面,擴展了刷新和關閉容器的方法
ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
User user = ioc.getBean(User.class);
System.out.println(user);
ioc.close();
}
5.5、具體的生命周期過程
-
bean對象創建(調用無參構造器)
-
給bean對象設置屬性
-
bean對象初始化之前操作(由bean的後置處理器負責)
-
bean對象初始化(需在配置bean時指定初始化方法)
-
bean對象初始化之後操作(由bean的後置處理器負責)
-
bean對象就緒可以使用
-
bean對象銷毀(需在配置bean時指定銷毀方法)
-
IOC容器關閉