Spring中Bean的生命周期使用解析
Bean的生命周期
解釋
(1)BeanFactoryPostProcessor的postProcessorBeanFactory()方法:若某個(gè)IoC容器內(nèi)添加了實(shí)現(xiàn)了BeanFactoryPostProcessor接口的實(shí)現(xiàn)類Bean,那么在該容器中實(shí)例化任何其他Bean之前可以回調(diào)該Bean中的postPrcessorBeanFactory()方法來對(duì)Bean的配置元數(shù)據(jù)進(jìn)行更改,比如從XML配置文件中獲取到的配置信息。
(2)Bean的實(shí)例化:Bean的實(shí)例化是使用反射實(shí)現(xiàn)的。
(3)Bean屬性注入:Bean實(shí)例化完成后,利用反射技術(shù)實(shí)現(xiàn)屬性及依賴Bean的注入。
(4)BeanNameAware的setBeanName()方法:如果某個(gè)Bean實(shí)現(xiàn)了BeanNameAware接口,那么Spring將會(huì)將Bean實(shí)例的ID傳遞給setBeanName()方法,在Bean類中新增一個(gè)beanName字段,并實(shí)現(xiàn)setBeanName()方法。
(5)BeanFactoryAware的setBeanFactory()方法:如果某個(gè)Bean實(shí)現(xiàn)了BeanFactoryAware接口,那么Spring將會(huì)將創(chuàng)建Bean的BeanFactory傳遞給setBeanFactory()方法,在Bean類中新增了一個(gè)beanFactory字段用來保存BeanFactory的值,并實(shí)現(xiàn)setBeanFactory()方法。
(6)ApplicationContextAware的setApplicationContext()方法:如果某個(gè)Bean實(shí)現(xiàn)了ApplicationContextAware接口,那么Spring將會(huì)將該Bean所在的上下文環(huán)境ApplicationContext傳遞給setApplicationContext()方法,在Bean類中新增一個(gè)ApplicationContext字段用來保存ApplicationContext的值,并實(shí)現(xiàn)setApplicationContext()方法。
(7)BeanPostProcessor預(yù)初始化方法:如果某個(gè)IoC容器中增加的實(shí)現(xiàn)BeanPostProcessor接口的實(shí)現(xiàn)類Bean,那么在該容器中實(shí)例化Bean之后,執(zhí)行初始化之前會(huì)調(diào)用BeanPostProcessor中的postProcessBeforeInitialization()方法執(zhí)行預(yù)初始化處理。
(8)InitializingBean的afterPropertiesSet()方法:如果Bean實(shí)現(xiàn)了InitializingBean接口,那么Bean在實(shí)例化完成后將會(huì)執(zhí)行接口中的afterPropertiesSet()方法來進(jìn)行初始化。
(9)自定義的inti-method指定的方法:如果配置文件中使用init-method屬性指定了初始化方法,那么Bean在實(shí)例化完成后將會(huì)調(diào)用該屬性指定的初始化方法進(jìn)行Bean的初始化。
(10)BeanPostProcessor初始化后方法:如果某個(gè)IoC容器中增加的實(shí)現(xiàn)BeanPostProcessor接口的實(shí)現(xiàn)類Bean,那么在該容器中實(shí)例化Bean之后并且完成初始化調(diào)用后執(zhí)行該接口中的postProcessorAfterInitialization()方法進(jìn)行初始化后處理。
(11)使用Bean:此時(shí)有關(guān)Bean的所有準(zhǔn)備工作均已完成,Bean可以被程序使用了,它們將會(huì)一直駐留在應(yīng)用上下文中,直到該上下文環(huán)境被銷毀。
(12)DisposableBean的destory()方法:如果Bean實(shí)現(xiàn)了DisposableBean接口,Spring將會(huì)在Bean實(shí)例銷毀之前調(diào)用該接口的destory()方法,來完成一些銷毀之前的處理工作。
(13)自定義的destory-method指定的方法:如果在配置文件中使用destory-method指定了銷毀方法,那么在Bean實(shí)例銷毀之前會(huì)調(diào)用該指定的方法完成一些銷毀之前的處理工作。
注意:
1、BeanFactoryPostProcessor接口與BeanPostProcessor接口的作用范圍是整個(gè)上下文環(huán)境中,使用方法是單獨(dú)新增一個(gè)類來實(shí)現(xiàn)這些接口,那么在處理其他Bean的某些時(shí)刻就會(huì)回調(diào)響應(yīng)的接口中的方法。
2、BeanNameAware、BeanFactoryAware、ApplicationContextAware的作用范圍的Bean范圍,即僅僅對(duì)實(shí)現(xiàn)了該接口的指定Bean有效,所有其使用方法是在要使用該功能的Bean自己來實(shí)現(xiàn)該接口。
3、第8點(diǎn)與第9點(diǎn)所述的兩個(gè)初始化方法作用是一樣的,我們完全可以使用其中的一種即可,一般情況我們使用第9點(diǎn)所述的方式,盡量少的去來Bean中實(shí)現(xiàn)某些接口,保持其獨(dú)立性,低耦合性,盡量不要與Spring代碼耦合在一起。第12和第13也是如此。
4、 在BeaFactoryAware's setBeanFactory()和Pre-initialization BeanPostProcessor之間還應(yīng)該有一步:調(diào)用ApplicationContextAware的setApplicationContext()方法。
可以看到Bean生命周期要經(jīng)歷很多階段,但這些階段大部分都是可選的。例如,某個(gè)Bean如果實(shí)現(xiàn)了BeanFactoryAware接口的setBeanFactory方法,那么該Bean的生命就會(huì)經(jīng)歷這個(gè)階段,如果不實(shí)現(xiàn)則沒有。
使用
public class Book implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean { private String bookName; public Book(){ System.out.println("Book Initializing "); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("Book.setBeanFactory invoke"); } @Override public void setBeanName(String name) { System.out.println("Book.setBeanName invoke"); } @Override public void destroy() throws Exception { System.out.println("Book.destory invoke"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("Book.afterPropertiesSet invoke"); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("Book.setApplicationContext invoke"); } public String getBookName() { return bookName; } public void setBookName(String bookName) { this.bookName = bookName; System.out.println("setBookName: Book name has set."); } public void myPostConstruct(){ System.out.println("Book.myPostConstruct invoke"); } // 自定義初始化方法 @PostConstruct public void springPostConstruct(){ System.out.println("@PostConstruct"); } public void myPreDestory(){ System.out.println("Book.myPreDestory invoke"); System.out.println("---------------destroy-----------------"); } // 自定義銷毀方法 @PreDestroy public void springPreDestory(){ System.out.println("@PreDestory"); } @Override protected void finalize() throws Throwable { System.out.println("------inside finalize-----"); } } public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { public MyBeanFactoryPostProcessor() { super(); System.out.println("這是BeanFactoryPostProcessor實(shí)現(xiàn)類構(gòu)造器??!"); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0) throws BeansException { System.out .println("BeanFactoryPostProcessor調(diào)用postProcessBeanFactory方法"); BeanDefinition bd = arg0.getBeanDefinition("book"); bd.getPropertyValues().addPropertyValue("bookName", "ddd"); } } // 通過注入調(diào)用 @Component public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if(bean instanceof Book){ System.out.println("MyBeanPostProcessor.postProcessBeforeInitialization"); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if(bean instanceof Book){ System.out.println("MyBeanPostProcessor.postProcessAfterInitialization"); } return bean; } } // ClassPathXmlApplicationContext 這個(gè)類實(shí)例化就會(huì)調(diào)用這個(gè)類 public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { public MyBeanFactoryPostProcessor() { super(); System.out.println("這是BeanFactoryPostProcessor實(shí)現(xiàn)類構(gòu)造器??!"); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0) throws BeansException { System.out .println("BeanFactoryPostProcessor調(diào)用postProcessBeanFactory方法"); BeanDefinition bd = arg0.getBeanDefinition("book"); bd.getPropertyValues().addPropertyValue("bookName", "ddd"); } } // InstantiationAwareBeanPostProcessor 接口本質(zhì)是BeanPostProcessor的子接口,一般我們繼承Spring為其提供的適配器類InstantiationAwareBeanPostProcessor Adapter來使用它,如下: public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter { public MyInstantiationAwareBeanPostProcessor() { super(); System.out .println("這是InstantiationAwareBeanPostProcessorAdapter實(shí)現(xiàn)類構(gòu)造器??!"); } // 接口方法、實(shí)例化Bean之前調(diào)用 @Override public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException { System.out .println("InstantiationAwareBeanPostProcessor調(diào)用postProcessBeforeInstantiation方法"); return null; } // 接口方法、實(shí)例化Bean之后調(diào)用 @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out .println("InstantiationAwareBeanPostProcessor調(diào)用postProcessAfterInitialization方法"); return bean; } // 接口方法、設(shè)置某個(gè)屬性時(shí)調(diào)用 @Override public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { System.out .println("InstantiationAwareBeanPostProcessor調(diào)用postProcessPropertyValues方法"); return pvs; } } // 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" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"> <bean id="beanPostProcessor" class="com.example.demo.MyBeanPostProcessor"> </bean> <bean id="instantiationAwareBeanPostProcessor" class="com.example.demo.MyInstantiationAwareBeanPostProcessor"> </bean> <bean id="beanFactoryPostProcessor" class="com.example.demo.MyBeanFactoryPostProcessor"> </bean> <bean id="book" class="com.example.demo.Book" init-method="myPostConstruct" destroy-method="myPreDestory"> <!-- 注入bean 屬性名稱 --> <property name="bookName" value="thingking in java" /> </bean> </beans> //調(diào)用 ApplicationContext context = new ClassPathXmlApplicationContext("beanconfig.xml"); Book book = (Book)context.getBean("book"); System.out.println("Book name = " + book.getBookName()); ((ClassPathXmlApplicationContext) context).destroy();
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Mybatis-plus:${ew.sqlselect}用法說明
這篇文章主要介紹了Mybatis-plus:${ew.sqlselect}用法說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06Java中的 BigDecimal 和 String 的相互轉(zhuǎn)換問題
這篇文章主要介紹了Java中的 BigDecimal 和 String 的相互轉(zhuǎn)換問題,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-05-05SpringBoot詳解如果通過@Value注解給靜態(tài)變量注入值
這篇文章主要介紹了springboot如何通過@Value給靜態(tài)變量注入值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06Java Lock接口實(shí)現(xiàn)原理及實(shí)例解析
這篇文章主要介紹了Java Lock接口實(shí)現(xiàn)原理及實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04基于SpringBoot集成測(cè)試遠(yuǎn)程連接Redis服務(wù)的教程詳解
這篇文章主要介紹了基于SpringBoot集成測(cè)試遠(yuǎn)程連接的Redis服務(wù)的相關(guān)知識(shí),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03java中LinkedBlockingQueue與ArrayBlockingQueue的異同
這篇文章主要介紹了java中LinkedBlockingQueue與ArrayBlockingQueue的異同,需要的朋友可以參考下2016-08-08