一、簡介
理解spring中bean的生命週期,對於學習和使用spring很有幫助。本文將從兩個角度對spring中bean
的生命週期進行介紹,一是bean定義生成;二是bean在初始化、使用、銷燬的生命週期中經歷的階段。
二、bean定義生成
bean定義生成主要分爲三個步驟,即bean定義的獲取、bean定義的註冊。
1、bean定義的獲取
bean的定義來源各種各樣,如xml定義、java註解定義等。
spring對各種來源提供了統一的接口org.springframework.core.io.Resource,
Resource接口即也是對spring內的所有底層資源進行了抽象(如file、url、classpath)。
Resource接口相關的類結構圖如下:
各類bean定義的加載請參數相應spring源碼。
2、bean定義的解析
由於來源的不同,bean的解析也是各種各樣的(如xml內標籤的解析)。
spring對bean的定義仍然有公共的接口org.springframework.beans.factory.config.BeanDefinition。
具體解析請查看spring源碼。
3、bean的註冊
解析得到的bean,最終會註冊到容器中,其實也就是ConcurrentHashMap,
即org.springframework.beans.factory.support.DefaultListableBeanFactory類中的實例變量
/** Map of bean definition objects, keyed by bean name */ private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
此bean的加載完成
三、spring的生命週期
spring生命週期中的階段,包括初始化、使用、銷燬。
1、初始化階段
1)調用bean的構造函數,創建實例;
2)進行參數依賴注入;
3)若實現org.springframework.beans.BeanNameAware接口,則調用BeanNameAware的setBeanName()方法;
4)若實現org.springframework.beans.factory.BeanClassLoaderAware接口,則調用BeanClassLoaderAware的setBeanClassLoader()方法;
5)若實現org.springframework.context.ApplicationContextAware接口,則調用ApplicationContextAware的setApplicationContext()方法;
6)若使用了註解@PostConstruct,則調相應方法;
7)若實現org.springframework.beans.factory.InitializingBean接口,則調用InitializingBean接口的afterPropertiesSet方法;
8)若bean定義的使用了initMethod,則調相應方法;
9)若實現org.springframework.beans.factory.config.BeanPostProcessor接口,則調用BeanPostProcessor的postProcessBeforeInitialization()方法和postProcessAfterInitialization方法;
2、使用階段
1)bean在項目的使用;
3、銷燬階段
1)若使用註解@PreDestroy,則調用相應方法;
2)若bean定義中配置了destroyMethod,則調用相應方法;
3)若實現org.springframework.beans.factory.DisposableBean接口,則調用DisposableBean接口的destroy方法;
四、bean生命週期示例
1、定義bean文件 SpringBeanLife.class
import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; public class SpringBeanLife implements BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, InitializingBean, BeanPostProcessor, DisposableBean { private String id; /******************* 下面是方法按時間執行的先後順序 *************************/ //初始化 SpringBeanLife() { System.out.println("bean init"); } //參數注入 public void setId(String id) { this.id = id; System.out.println("invoke set method"); } //來自BeanNameAware @Override public void setBeanName(String name) { System.out.println("invoke setBeanName"); } //來自BeanClassLoaderAware @Override public void setBeanClassLoader(ClassLoader classLoader) { System.out.println("invoke setBeanClassLoader"); } //來自ApplicationContextAware @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("invoke setApplicationContext"); } //來自注解@PostConstruct @PostConstruct public void postConstructMethod() { System.out.println("invoke postConstructMethod"); } //來自InitializingBean @Override public void afterPropertiesSet() throws Exception { System.out.println("invoke afterPropertiesSet"); } //來自配置initMethod = "initMethod" public void initMethod() { System.out.println("invoke init-method"); } //來自BeanPostProcessor @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("invoke postProcessBeforeInitialization"); return bean; } //來自BeanPostProcessor @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("invoke postProcessAfterInitialization"); return bean; } //bean使用(如此時調用了下面的use方法) public void use() { System.out.println("use bean"); } //來自注解@PreDestroy @PreDestroy public void preDestroyMethod() { System.out.println("invoke preDestroyMethod"); } //來自bean定義中的配置destroyMethod = "destoryMethod" public void destoryMethod() { System.out.println("invoke destory-method"); } //來自DisposableBean @Override public void destroy() throws Exception { System.out.println("invoke destroy"); } }
2、測試
import org.springframework.beans.factory.annotation.Configurable; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; @Configurable public class SpringConfig { @Bean(initMethod = "initMethod", destroyMethod = "destoryMethod") public SpringBeanLife springBeanLife() { SpringBeanLife bean = new SpringBeanLife(); bean.setId("001"); return bean; } public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class); SpringBeanLife bean = ctx.getBean(SpringBeanLife.class); bean.use(); ctx.close(); } }
輸出:
bean init
invoke set method
invoke setBeanName
invoke setBeanClassLoader
invoke setApplicationContext
invoke postConstructMethod
invoke afterPropertiesSet
invoke init-method
invoke postProcessBeforeInitialization
invoke postProcessAfterInitialization
invoke postProcessBeforeInitialization
invoke postProcessAfterInitialization
use bean
invoke preDestroyMethod
invoke destroy
invoke destory-method