- 作者簡介:大家好,我是五度魚,一個普通的Java領(lǐng)域博主,不停輸出Java技術(shù)博客和干貨。
- 座右銘:鍥而不舍,金石可鏤。
- 個人主頁:五度魚學(xué)Java的主頁
前言
在Java
中,Bean
是一個重要的概念,它代表了應(yīng)用程序中的一個對象。在開發(fā)中,我們經(jīng)常使用Bean
來管理對象的生命周期。本文將介紹Bean
的生命周期,并詳細(xì)講解如何在Spring
框架中管理Bean
的生命周期。
1. 什么是Bean的生命周期?
Spring
其實(shí)就是一個管理Bean
對象的工廠。它負(fù)責(zé)對象的創(chuàng)建,對象的銷毀等。
所謂的生命周期就是:對象從創(chuàng)建開始到最終銷毀的整個過程。Spring
為每個Bean
定義了若干個回調(diào)方法,使得開發(fā)人員可以在某個特定的時(shí)間點(diǎn)對Bean進(jìn)行特定的操作。
2. 為什么要知道Bean的生命周期?
其實(shí)生命周期的本質(zhì)是:在哪個時(shí)間節(jié)點(diǎn)上調(diào)用了哪個類的哪個方法。
我們需要充分的了解在這個生命線上,都有哪些特殊的時(shí)間節(jié)點(diǎn)。
只有我們知道了特殊的時(shí)間節(jié)點(diǎn)都在哪,到時(shí)我們才可以確定代碼寫到哪。
我們可能需要在某個特殊的時(shí)間點(diǎn)上執(zhí)行一段特定的代碼,這段代碼就可以放到這個節(jié)點(diǎn)上。當(dāng)生命線走到這里的時(shí)候,自然會被調(diào)用。
3. Bean的生命周期之5步
Bean
生命周期的管理,可以參考Spring
的源碼:AbstractAutowireCapableBeanFactory
類的doCreateBean()
方法。`
Bean生命周期可以粗略的劃分為五大步:
- 第一步:實(shí)例化
Bean
- 第二步:Bean屬性賦值
- 第三步:初始化
Bean
- 第四步:使用
Bean
- 第五步:銷毀
Bean
編寫測試程序:
定義一個Bean
package com.powernode.spring6.bean;
/**
* @author 五度魚
* @version 1.0
* @className User
* @since 1.0
**/
public class User {
private String name;
public User() {
System.out.println("1.實(shí)例化Bean");
}
public void setName(String name) {
this.name = name;
System.out.println("2.Bean屬性賦值");
}
public void initBean(){
System.out.println("3.初始化Bean");
}
public void destroyBean(){
System.out.println("5.銷毀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="userBean" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean">
<property name="name" value="zhangsan"/>
</bean>
</beans>
package com.powernode.spring6.test;
import com.powernode.spring6.bean.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author 五度魚
* @version 1.0
* @className BeanLifecycleTest
* @since 1.0
**/
public class BeanLifecycleTest {
@Test
public void testLifecycle(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
User userBean = applicationContext.getBean("userBean", User.class);
System.out.println("4.使用Bean");
// 只有正常關(guān)閉spring容器才會執(zhí)行銷毀方法
ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;
context.close();
}
}
執(zhí)行結(jié)果:
需要注意的:
- 第一:只有正常關(guān)閉spring容器,bean的銷毀方法才會被調(diào)用。
- 第二:
ClassPathXmlApplicationContext
類才有close()方法。 - 第三:配置文件中的init-method指定初始化方法。
destroy-method
指定銷毀方法。
4. Bean的生命周期之7步
在以上的5步中,第3步是初始化Bean,如果你還想在初始化前和初始化后添加代碼,可以加入“Bean后處理器”。
編寫一個類實(shí)現(xiàn)BeanPostProcessor
類,并且重寫before和after方法:
package com.powernode.spring6.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* @author 五度魚
* @version 1.0
* @className LogBeanPostProcessor
* @since 1.0
**/
public class LogBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Bean后處理器的before方法執(zhí)行,即將開始初始化");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Bean后處理器的after方法執(zhí)行,已完成初始化");
return bean;
}
}
在spring.xml
文件中配置“Bean后處理器”:
<!--配置Bean后處理器。這個后處理器將作用于當(dāng)前配置文件中所有的bean。-->
<bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/>
一定要注意:在spring.xml
文件中配置的Bean
后處理器將作用于當(dāng)前配置文件中所有的Bean
。
執(zhí)行測試程序:
如果加上Bean后處理器
的話,Bean
的生命周期就是7步了:
5. Bean的生命周期之10步
如果根據(jù)源碼跟蹤,可以劃分更細(xì)粒度的步驟,10步:
上圖中檢查Bean是否實(shí)現(xiàn)了Aware
的相關(guān)接口是什么意思?
Aware
相關(guān)的接口包括:BeanNameAware
、BeanClassLoaderAware
、BeanFactoryAware
- 當(dāng)
Bean
實(shí)現(xiàn)了BeanNameAware
,Spring
會將Bean
的名字傳遞給Bean。 - 當(dāng)
Bean
實(shí)現(xiàn)了BeanClassLoaderAware
,Spring
會將加載該Bean
的類加載器傳遞給Bean。 - 當(dāng)
Bean
實(shí)現(xiàn)了BeanFactoryAware
,Spring
會將Bean
工廠對象傳遞給Bean
。
測試以上10步,可以讓User
類實(shí)現(xiàn)5個接口,并實(shí)現(xiàn)所有方法:
BeanNameAware
BeanClassLoaderAware
BeanFactoryAware
InitializingBean
DisposableBean
代碼如下:
package com.powernode.spring6.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
/**
* @author 五度魚
* @version 1.0
* @className User
* @since 1.0
**/
public class User implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {
private String name;
public User() {
System.out.println("1.實(shí)例化Bean");
}
public void setName(String name) {
this.name = name;
System.out.println("2.Bean屬性賦值");
}
public void initBean(){
System.out.println("6.初始化Bean");
}
public void destroyBean(){
System.out.println("10.銷毀Bean");
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("3.類加載器:" + classLoader);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("3.Bean工廠:" + beanFactory);
}
@Override
public void setBeanName(String name) {
System.out.println("3.bean名字:" + name);
}
@Override
public void destroy() throws Exception {
System.out.println("9.DisposableBean destroy");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("5.afterPropertiesSet執(zhí)行");
}
}
package com.powernode.spring6.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* @author 五度魚
* @version 1.0
* @className LogBeanPostProcessor
* @since 1.0
**/
public class LogBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("4.Bean后處理器的before方法執(zhí)行,即將開始初始化");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("7.Bean后處理器的after方法執(zhí)行,已完成初始化");
return bean;
}
}
執(zhí)行結(jié)果:
通過測試可以看出來:
InitializingBean
的方法早于init-method
的執(zhí)行。DisposableBean
的方法早于destroy-method
的執(zhí)行。
對于SpringBean
的生命周期,掌握之前的7步即可。夠用。
6. Bean的作用域不同,管理方式不同
Spring
根據(jù)Bean
的作用域來選擇管理方式。
- 對于
singleton
作用域的Bean
,Spring
能夠精確地知道該Bean
何時(shí)被創(chuàng)建,何時(shí)初始化完成,以及何時(shí)被銷毀; - 而對于
prototype
作用域的Bean
,Spring
只負(fù)責(zé)創(chuàng)建,當(dāng)容器創(chuàng)建了Bean
的實(shí)例后,Bean
的實(shí)例就交給客戶端代碼管理,Spring
容器將不再跟蹤其生命周期。
把之前User
類的spring.xml
文件中的配置scope
設(shè)置為prototype
:
<?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="userBean" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean" scope="prototype">
<property name="name" value="zhangsan"/>
</bean>
<!--配置Bean后處理器。這個后處理器將作用于當(dāng)前配置文件中所有的bean。-->
<bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/>
</beans>
執(zhí)行測試程序:
通過測試一目了然。只執(zhí)行了前8步,第9和10都沒有執(zhí)行。
7. 自己new的對象如何讓Spring管理
有些時(shí)候可能會遇到這樣的需求,某個java對象是我們自己new的,然后我們希望這個對象被Spring容器管理,怎么實(shí)現(xiàn)?文章來源:http://www.zghlxwxcb.cn/news/detail-795398.html
package com.powernode.spring6.bean;
/**
* @author 五度魚
* @version 1.0
* @className User
* @since 1.0
**/
public class User {
}
package com.powernode.spring6.test;
import com.powernode.spring6.bean.User;
import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
/**
* @author 五度魚
* @version 1.0
* @className RegisterBeanTest
* @since 1.0
**/
public class RegisterBeanTest {
@Test
public void testBeanRegister(){
// 自己new的對象
User user = new User();
System.out.println(user);
// 創(chuàng)建 默認(rèn)可列表BeanFactory 對象
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// 注冊Bean
factory.registerSingleton("userBean", user);
// 從spring容器中獲取bean
User userBean = factory.getBean("userBean", User.class);
System.out.println(userBean);
}
}
最后求個關(guān)注,點(diǎn)贊,收藏,謝謝!文章來源地址http://www.zghlxwxcb.cn/news/detail-795398.html
到了這里,關(guān)于【Spring】Spring的Bean的生命周期的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!