前言
Spring框架是一個(gè)非常流行的Java企業(yè)級(jí)應(yīng)用程序框架,已經(jīng)成為許多生產(chǎn)環(huán)境中的首選技術(shù)。它提供了一種便捷的方法來幫助開發(fā)人員構(gòu)建可擴(kuò)展和模塊化的企業(yè)級(jí)應(yīng)用程序。在Spring框架中,Bean生命周期是非常重要的一部分,它負(fù)責(zé)Bean的創(chuàng)建和銷毀。
一個(gè)完整的Spring的Bean的生命周期
Spring框架中Bean的完整生命周期包括:
- 實(shí)例化Bean
- 設(shè)置對(duì)象屬性
- 對(duì)Bean執(zhí)行用戶定義的初始化方法
- Bean可用
- 關(guān)閉容器
實(shí)例化Bean
在 Spring 中,實(shí)例化 Bean 主要有兩種方式:使用構(gòu)造函數(shù)實(shí)例化和使用靜態(tài)工廠方法實(shí)例化。
構(gòu)造函數(shù)實(shí)例化是使用類的構(gòu)造函數(shù)創(chuàng)建 Bean 對(duì)象的方式。在 Spring 配置文件中,可以通過 元素的 constructor-arg 子元素來指定 Bean 的構(gòu)造函數(shù)參數(shù)。
靜態(tài)工廠方法實(shí)例化是指在 BeanFactory 創(chuàng)建 Bean 實(shí)例時(shí),調(diào)用靜態(tài)工廠方法創(chuàng)建 Bean 對(duì)象。在 Spring 配置文件中,可以通過 元素的 class 屬性和 factory-method 屬性來指定 Bean 工廠類和工廠方法。
需要注意的是,在 Spring 中,Bean 實(shí)例化后并不直接進(jìn)入使用狀態(tài),而是存放在 BeanFactory 中,等待被其他 Bean 使用。如果沒有配置 Bean 的作用域?yàn)?singleton,則每次使用 Bean 時(shí)都會(huì)創(chuàng)建一個(gè)新的 Bean 實(shí)例。
在Bean實(shí)例化的時(shí)候,有幾個(gè)比較重要的接口,我們可以看下。
1. BeanFactoryPostProcessor
BeanFactoryPostProcessor它能夠讓開發(fā)人員在Bean工廠創(chuàng)建Bean之前對(duì)其進(jìn)行配置或修改,同時(shí)還能在Bean實(shí)例化之前進(jìn)行一些定制化操作。通過BeanFactoryPostProcessor接口,開發(fā)人員可以訪問到Spring容器內(nèi)的BeanFactory,從而改變Bean的配置信息,例如將某個(gè)Bean的scope從singleton改變?yōu)閜rototype。
BeanFactoryPostProcessor接口包括一個(gè)方法postProcessBeanFactory( ConfigurableListableBeanFactory beanFactory ),它接收一個(gè)ConfigurableListableBeanFactory對(duì)象作為參數(shù),這個(gè)對(duì)象可以被用來修改BeanFactory的配置。實(shí)現(xiàn)自定義BeanFactoryPostProcessor非常簡(jiǎn)單:只需要?jiǎng)?chuàng)建一個(gè)實(shí)現(xiàn)該接口的類,并在Spring配置文件中聲明Bean即可。
2. BeanPostProcessor
當(dāng)我們?cè)趧?chuàng)建Bean的時(shí)候,Spring框架會(huì)按照Bean的生命周期方法先后順序執(zhí)行相應(yīng)的方法。其中BeanPostProcessor接口定義了兩個(gè)方法,beforeInitialization和afterInitialization,用于在Bean初始化前和Bean初始化后進(jìn)行處理。
BeanPostProcessor的主要作用是對(duì)Bean的實(shí)例進(jìn)行后置處理。在Bean實(shí)例創(chuàng)建完成之后,BeanPostProcessor實(shí)例會(huì)對(duì)Bean進(jìn)行一些額外的處理,或者說是修飾。例如,開發(fā)人員可以借助于BeanPostProcessor來實(shí)現(xiàn)一些非侵入式的集中式日志記錄或者為Bean裝配前初始化某些屬性值,以及為Bean設(shè)置代理等。
設(shè)置對(duì)象屬性
設(shè)置對(duì)象屬性是Spring Bean生命周期中的一個(gè)階段。在這個(gè)階段,Spring框架會(huì)根據(jù)Bean的配置信息為對(duì)象設(shè)置屬性并將其裝配到應(yīng)用程序中。
具體實(shí)現(xiàn)方法是在Bean的配置信息中添加屬性元素,用于配置對(duì)象的屬性值。例如:
<bean id="exampleBean" class="com.example.Example">
<property name="name" value="John Doe" />
<property name="age" value="30" />
</bean>
在上面的例子中,我們定義了一個(gè)名為exampleBean的Bean,它的類是com.example.Example。我們使用元素設(shè)置了對(duì)象的兩個(gè)屬性:name和age??梢钥吹剑覀兺ㄟ^name屬性指定了要設(shè)置的屬性名,通過value屬性指定要設(shè)置的屬性值。Spring框架將使用反射機(jī)制調(diào)用對(duì)象的setter方法,并將屬性值設(shè)置為參數(shù)。
另外,在使用注解的方式配置Bean時(shí),也可以使用@Autowired注解或者@Resource注解為對(duì)象的屬性進(jìn)行自動(dòng)裝配。這些注解可以根據(jù)Type或Name自動(dòng)查找適配的Bean進(jìn)行裝配,從而減少了手動(dòng)配置Bean屬性的工作。例如:
@Component
public class ExampleComponent {
@Autowired
private ExampleBean exampleBean;
public void doSomething() {
// 使用exampleBean對(duì)象執(zhí)行一些操作
}
}
@Component
public class ExampleBean {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
在上面的例子中,我們定義了一個(gè)使用@Autowired注解進(jìn)行注入的ExampleComponent 組件,并將其屬性exampleBean注入了一個(gè)ExampleBean對(duì)象。當(dāng)Spring框架啟動(dòng)時(shí),它會(huì)自動(dòng)為ExampleComponent組件實(shí)例化對(duì)象,并調(diào)用setter方法將exampleBean對(duì)象注入到ExampleComponent中。
對(duì)Bean執(zhí)行用戶定義的初始化方法
對(duì)Bean執(zhí)行用戶定義的初始化方法在Spring框架中是通過Bean的生命周期回調(diào)方法來實(shí)現(xiàn)的。具體步驟如下:
1. 實(shí)現(xiàn)InitializingBean
InitializingBean是Spring框架中一個(gè)非常重要的接口之一,定義了Bean初始化后要執(zhí)行的操作。在BeanFactory完成對(duì)Bean實(shí)例的配置和添加Bean實(shí)例的前置和后置處理工作之后,Spring容器將調(diào)用InitializingBean接口的afterPropertiesSet方法進(jìn)行Bean的初始化執(zhí)行操作。
在Spring容器中,實(shí)現(xiàn)InitializingBean接口的類變得非常重要,它允許開發(fā)人員控制Bean的完整生命周期。開發(fā)人員可以借助于afterPropertiesSet方法,為Bean初始化一些數(shù)據(jù)或者修飾/驗(yàn)證已經(jīng)設(shè)置的某些依賴。
在Bean類中實(shí)現(xiàn)InitializingBean接口,該接口中定義了一個(gè)afterPropertiesSet()方法,該方法會(huì)在Bean初始化完成之后被調(diào)用。
public class MyBean implements InitializingBean {
// ...
@Override
public void afterPropertiesSet() throws Exception {
// 在這里編寫B(tài)ean初始化的邏輯
// ...
}
// ...
}
2. 使用@PostConstruct注解
還可以使用@PostConstruct注解,在Bean初始化完成之后執(zhí)行指定的方法,例如:
public class MyBean {
// ...
@PostConstruct
public void init() {
// 在這里編寫B(tài)ean初始化的邏輯
// ...
}
// ...
}
3. 指定init方法
也可以在XML配置文件中指定Bean初始化時(shí)調(diào)用的方法,例如:
<bean id="myBean" class="com.example.MyBean" init-method="init"/>
其中,init-method屬性指定了Bean初始化時(shí)要調(diào)用的方法名。
以上是三種常用的對(duì)Bean執(zhí)行用戶定義的初始化方法的實(shí)現(xiàn)方式,您可以根據(jù)具體情況選擇其中的一種方式。
Bean可用
簡(jiǎn)單來說,在Spring生命周期中,Bean可用是在BeanFactory啟動(dòng)階段的某個(gè)時(shí)刻被觸發(fā)的,表示這個(gè)Bean已經(jīng)完成了所有的初始化工作,可以被其他Bean調(diào)用和使用。在這個(gè)狀態(tài)下,Bean已經(jīng)處于正常運(yùn)行狀態(tài),可以對(duì)外提供服務(wù)或者處理業(yè)務(wù)邏輯。
這里提供一個(gè)簡(jiǎn)單的Spring生命周期Bean可用的示例代碼。首先,我們定義一個(gè)名為BeanLifeCycleDemo
的類,并指定初始化和銷毀方法。代碼如下:
public class BeanLifeCycleDemo {
private String message;
public void init() {
System.out.println("Bean is being initialized.");
this.message = "Hello, world!";
}
public void destroy() {
System.out.println("Bean is being destroyed.");
}
public String getMessage() {
return this.message;
}
public void setMessage(String message) {
this.message = message;
}
}
接下來,我們需要在Spring配置文件中聲明這個(gè)類的Bean,并指定它的初始化和銷毀方法。配置文件為beans.xml
,代碼如下:
<bean id="beanLifeCycleDemo" class="com.example.BeanLifeCycleDemo"
init-method="init" destroy-method="destroy">
<property name="message" value="Hello, world!"/>
</bean>
在這個(gè)示例中,我們使用了Spring的依賴注入功能,將屬性
message
設(shè)置為Hello, world!
。同時(shí),我們指定了Bean的初始化方法為init()
,和銷毀方法為destroy()
。
最后,我們創(chuàng)建一個(gè)測(cè)試類AppTest
,并在其中測(cè)試輸出Bean的信息。代碼如下:
public class AppTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("beans.xml");
BeanLifeCycleDemo bean = context.getBean("beanLifeCycleDemo", BeanLifeCycleDemo.class);
System.out.println(bean.getMessage());
context.close();
}
}
在這個(gè)測(cè)試類中,我們使用
ClassPathXmlApplicationContext
類創(chuàng)建了Spring容器,并通過context.getBean()
方法獲取了Bean實(shí)例。然后,我們輸出了Bean的信息,即Hello, world!
,并調(diào)用了context.close()
方法,銷毀了Bean。在控制臺(tái)輸出中,我們可以看到初始化方法“Bean is being initialized.”和銷毀方法“Bean is being destroyed.”的信息。
通過以上示例,我們可以看到,在Spring生命周期中,Bean可用是在Bean初始化完成后被觸發(fā)的。在這個(gè)狀態(tài)下,我們可以對(duì)Bean進(jìn)行操作,包括調(diào)用它的方法、獲取它的屬性等。
關(guān)閉容器
在 Spring 框架中,Bean 生命周期的最后一個(gè)階段是關(guān)閉容器,即當(dāng)應(yīng)用程序完成運(yùn)行時(shí),應(yīng)調(diào)用 ApplicationContext 的 close() 方法,以便釋放所有資源和 Bean 所占用的內(nèi)存。當(dāng) ApplicationContext 關(guān)閉時(shí),它會(huì)通知 Bean,以便它們可以對(duì)關(guān)閉操作作出響應(yīng)。
以下是關(guān)閉容器時(shí) Bean 生命周期涉及的步驟:
- 當(dāng) BeanFactory 關(guān)閉時(shí),將調(diào)用所有 DisposableBean 實(shí)例的 destroy() 方法。
DisposableBean是Spring框架中一個(gè)很關(guān)鍵的接口。它定義了Bean在銷毀時(shí)要執(zhí)行的操作。在一個(gè)Bean被容器實(shí)例化之后,在容器銷毀Bean之前,會(huì)調(diào)用Bean實(shí)現(xiàn)的這個(gè)接口。最常見的操作包括關(guān)閉數(shù)據(jù)庫(kù)連接或停止根據(jù)消息隊(duì)列執(zhí)行的任務(wù)。如果有需要在Bean銷毀之前釋放某些資源,那么實(shí)現(xiàn)DisposableBean是很重要的。
-
如果 Bean 實(shí)現(xiàn)了 DisposableBean 接口,則調(diào)用 destroy() 方法。這個(gè)方法允許 Bean 清理任何在應(yīng)用程序運(yùn)行時(shí)已經(jīng)初始化或記錄的資源。
-
調(diào)用在 Bean 定義中定義的任何自定義銷毀方法。自定義銷毀方法可以通過指定 destroy-method 屬性來定義。例如:
<bean id="myBean" class="com.example.MyBean" destroy-method="cleanup"/>
這里的 cleanup() 方法將在關(guān)閉容器時(shí)被調(diào)用。
-
關(guān)閉內(nèi)部 bean 容器。
如果 bean 是 ApplicationContext 的子容器,則首先關(guān)閉子容器中的 bean。然后關(guān)閉 ApplicationContext 自身,以確保所有 bean 處于已銷毀狀態(tài)。
需要注意的是,在應(yīng)用程序關(guān)閉時(shí),所有的資源,如數(shù)據(jù)庫(kù)連接、文件句柄等,必須被有效地釋放。因此,實(shí)現(xiàn) destroy() 和自定義銷毀方法是非常重要的。通過這些方法,可以確保 bean 釋放所有的資源,并在關(guān)閉應(yīng)用程序時(shí)正確地退出。
除了使用銷毀方法之外,還可以使用注解來標(biāo)注Bean的初始化和銷毀方法。@PostConstruct和@PreDestroy是兩個(gè)Spring框架中內(nèi)置的注解,這些注解可以使用在任何方法上,只要符合Bean的規(guī)范即可。
@PostConstruct注解在Bean的初始化之后調(diào)用,@PreDestroy注解則在Bean被銷毀之前調(diào)用。在使用注解的時(shí)候,只需要定義需要執(zhí)行的方法,就可以同時(shí)實(shí)現(xiàn)Bean初始化和銷毀的效果。
文章來源:http://www.zghlxwxcb.cn/news/detail-476918.html
結(jié)論
Spring的Bean生命周期可以分為兩個(gè)階段:BeanFactory準(zhǔn)備和BeanFactory啟動(dòng),其中Bean創(chuàng)建、初始化、銷毀等過程都在這個(gè)時(shí)間段內(nèi)完成。在BeanFactory準(zhǔn)備階段,Spring容器對(duì)BeanFactory進(jìn)行了初始化,包括加載配置文件、實(shí)例化Bean工廠等。在該階段,調(diào)用了Bean Factory Post Processor(BFPP)和Bean Post Processor(BPP)等接口,對(duì)FactoryBean和普通Bean進(jìn)行預(yù)處理。在BeanFactory啟動(dòng)階段,Spring容器啟動(dòng)后會(huì)實(shí)例化所有的Bean,并根據(jù)定義的屬性、依賴等設(shè)置對(duì)Bean進(jìn)行初始化。在這個(gè)過程中,調(diào)用了Bean的構(gòu)造函數(shù)和初始化方法,對(duì)Bean進(jìn)行了依賴注入等操作,同時(shí)也觸發(fā)了Bean可以使用的狀態(tài)。在容器關(guān)閉時(shí),Spring會(huì)調(diào)用Bean的銷毀方法以進(jìn)行一些清理工作。文章來源地址http://www.zghlxwxcb.cn/news/detail-476918.html
到了這里,關(guān)于淺析Spring生命周期的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!