當前位置:
首頁 > 知識 > Spring Bean的生命周期(詳細)

Spring Bean的生命周期(詳細)

Spring作為當前Java最流行、最強大的輕量級框架,受到了程序員的熱烈歡迎。準確的了解Spring Bean的生命周期是非常必要的。我們通常使用ApplicationContext作為Spring容器。這裡,我們講的也是 ApplicationContext中Bean的生命周期。而實際上BeanFactory也是差不多的,只不過處理器需要手動註冊。

轉載請註明地址 http://www.cnblogs.com/zrtqsk/p/3735273.html,謝謝。

一、生命周期流程圖:

Spring Bean的完整生命周期從創建Spring容器開始,直到最終Spring容器銷毀Bean,這其中包含了一系列關鍵點。

Spring Bean的生命周期(詳細)

Spring Bean的生命周期(詳細)

若容器註冊了以上各種介面,程序那麼將會按照以上的流程進行。下面將仔細講解各介面作用。

二、各種介面方法分類

Bean的完整生命周期經歷了各種方法調用,這些方法可以劃分為以下幾類:

1、Bean自身的方法 : 這個包括了Bean本身調用的方法和通過配置文件中<bean>的init-method和destroy-method指定的方法

2、Bean級生命周期介面方法 : 這個包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean這些介面的方法

3、容器級生命周期介面方法 : 這個包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 這兩個介面實現,一般稱它們的實現類為「後處理器」。

4、工廠後處理器介面方法 : 這個包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工廠後處理器 介面的方法。工廠後處理器也是容器級的。在應用上下文裝配配置文件之後立即調用。

三、演示

我們用一個簡單的Spring Bean來演示一下Spring Bean的生命周期。

1、首先是一個簡單的Spring Bean,調用Bean自身的方法和Bean級生命周期介面方法,為了方便演示,它實現了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean這4個介面,同時有2個方法,對應配置文件中<bean>的init-method和destroy-method。如下:

1 package springBeanTest;

2

3 import org.springframework.beans.BeansException;

4 import org.springframework.beans.factory.BeanFactory;

5 import org.springframework.beans.factory.BeanFactoryAware;

6 import org.springframework.beans.factory.BeanNameAware;

7 import org.springframework.beans.factory.DisposableBean;

8 import org.springframework.beans.factory.InitializingBean;

9

10 /**

11 * @author qsk

12 */

13 public class Person implements BeanFactoryAware, BeanNameAware,

14 InitializingBean, DisposableBean {

15

16 private String name;

17 private String address;

18 private int phone;

19

20 private BeanFactory beanFactory;

21 private String beanName;

22

23 public Person() {

24 System.out.println("【構造器】調用Person的構造器實例化");

25 }

26

27 public String getName() {

28 return name;

29 }

30

31 public void setName(String name) {

32 System.out.println("【注入屬性】注入屬性name");

33 this.name = name;

34 }

35

36 public String getAddress() {

37 return address;

38 }

39

40 public void setAddress(String address) {

41 System.out.println("【注入屬性】注入屬性address");

42 this.address = address;

43 }

44

45 public int getPhone() {

46 return phone;

47 }

48

49 public void setPhone(int phone) {

50 System.out.println("【注入屬性】注入屬性phone");

51 this.phone = phone;

52 }

53

54 @Override

55 public String toString() {

56 return "Person [address=" + address + ", name=" + name + ", phone="

57 + phone + "]";

58 }

59

60 // 這是BeanFactoryAware介面方法

61 @Override

62 public void setBeanFactory(BeanFactory arg0) throws BeansException {

63 System.out

64 .println("【BeanFactoryAware介面】調用BeanFactoryAware.setBeanFactory()");

65 this.beanFactory = arg0;

66 }

67

68 // 這是BeanNameAware介面方法

69 @Override

70 public void setBeanName(String arg0) {

71 System.out.println("【BeanNameAware介面】調用BeanNameAware.setBeanName()");

72 this.beanName = arg0;

73 }

74

75 // 這是InitializingBean介面方法

76 @Override

77 public void afterPropertiesSet() throws Exception {

78 System.out

79 .println("【InitializingBean介面】調用InitializingBean.afterPropertiesSet()");

80 }

81

82 // 這是DiposibleBean介面方法

83 @Override

84 public void destroy() throws Exception {

85 System.out.println("【DiposibleBean介面】調用DiposibleBean.destory()");

86 }

87

88 // 通過<bean>的init-method屬性指定的初始化方法

89 public void myInit() {

90 System.out.println("【init-method】調用<bean>的init-method屬性指定的初始化方法");

91 }

92

93 // 通過<bean>的destroy-method屬性指定的初始化方法

94 public void myDestory() {

95 System.out.println("【destroy-method】調用<bean>的destroy-method屬性指定的初始化方法");

96 }

97 }

2、接下來是演示BeanPostProcessor介面的方法,如下:

1 package springBeanTest;

2

3 import org.springframework.beans.BeansException;

4 import org.springframework.beans.factory.config.BeanPostProcessor;

5

6 public class MyBeanPostProcessor implements BeanPostProcessor {

7

8 public MyBeanPostProcessor() {

9 super();

10 System.out.println("這是BeanPostProcessor實現類構造器!!");

11 // TODO Auto-generated constructor stub

12 }

13

14 @Override

15 public Object postProcessAfterInitialization(Object arg0, String arg1)

16 throws BeansException {

17 System.out

18 .println("BeanPostProcessor介面方法postProcessAfterInitialization對屬性進行更改!");

19 return arg0;

20 }

21

22 @Override

23 public Object postProcessBeforeInitialization(Object arg0, String arg1)

24 throws BeansException {

25 System.out

26 .println("BeanPostProcessor介面方法postProcessBeforeInitialization對屬性進行更改!");

27 return arg0;

28 }

29 }

如上,BeanPostProcessor介面包括2個方法postProcessAfterInitialization和postProcessBeforeInitialization,這兩個方法的第一個參數都是要處理的Bean對象,第二個參數都是Bean的name。返回值也都是要處理的Bean對象。這裡要注意。

3、InstantiationAwareBeanPostProcessor 介面本質是BeanPostProcessor的子介面,一般我們繼承Spring為其提供的適配器類InstantiationAwareBeanPostProcessor Adapter來使用它,如下:

1 package springBeanTest;

2

3 import java.beans.PropertyDescriptor;

4

5 import org.springframework.beans.BeansException;

6 import org.springframework.beans.PropertyValues;

7 import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;

8

9 public class MyInstantiationAwareBeanPostProcessor extends

10 InstantiationAwareBeanPostProcessorAdapter {

11

12 public MyInstantiationAwareBeanPostProcessor() {

13 super();

14 System.out

15 .println("這是InstantiationAwareBeanPostProcessorAdapter實現類構造器!!");

16 }

17

18 // 介面方法、實例化Bean之前調用

19 @Override

20 public Object postProcessBeforeInstantiation(Class beanClass,

21 String beanName) throws BeansException {

22 System.out

23 .println("InstantiationAwareBeanPostProcessor調用postProcessBeforeInstantiation方法");

24 return null;

25 }

26

27 // 介面方法、實例化Bean之後調用

28 @Override

29 public Object postProcessAfterInitialization(Object bean, String beanName)

30 throws BeansException {

31 System.out

32 .println("InstantiationAwareBeanPostProcessor調用postProcessAfterInitialization方法");

33 return bean;

34 }

35

36 // 介面方法、設置某個屬性時調用

37 @Override

38 public PropertyValues postProcessPropertyValues(PropertyValues pvs,

39 PropertyDescriptor[] pds, Object bean, String beanName)

40 throws BeansException {

41 System.out

42 .println("InstantiationAwareBeanPostProcessor調用postProcessPropertyValues方法");

43 return pvs;

44 }

45 }

這個有3個方法,其中第二個方法postProcessAfterInitialization就是重寫了BeanPostProcessor的方法。第三個方法postProcessPropertyValues用來操作屬性,返回值也應該是PropertyValues對象。

4、演示工廠後處理器介面方法,如下:

1 package springBeanTest;

2

3 import org.springframework.beans.BeansException;

4 import org.springframework.beans.factory.config.BeanDefinition;

5 import org.springframework.beans.factory.config.BeanFactoryPostProcessor;

6 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

7

8 public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

9

10 public MyBeanFactoryPostProcessor() {

11 super();

12 System.out.println("這是BeanFactoryPostProcessor實現類構造器!!");

13 }

14

15 @Override

16 public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)

17 throws BeansException {

18 System.out

19 .println("BeanFactoryPostProcessor調用postProcessBeanFactory方法");

20 BeanDefinition bd = arg0.getBeanDefinition("person");

21 bd.getPropertyValues().addPropertyValue("phone", "110");

22 }

23

24 }

5、配置文件如下beans.xml,很簡單,使用ApplicationContext,處理器不用手動註冊:

<?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="springBeanTest.MyBeanPostProcessor">

</bean>

<bean id="instantiationAwareBeanPostProcessor" class="springBeanTest.MyInstantiationAwareBeanPostProcessor">

</bean>

<bean id="beanFactoryPostProcessor" class="springBeanTest.MyBeanFactoryPostProcessor">

</bean>

<bean id="person" class="springBeanTest.Person" init-method="myInit"

destroy-method="myDestory" scope="singleton" p:name="張三" p:address="廣州"

p:phone="15900000000" />

</beans>

6、下面測試一下:

1 package springBeanTest;

2

3 import org.springframework.context.ApplicationContext;

4 import org.springframework.context.support.ClassPathXmlApplicationContext;

5

6 public class BeanLifeCycle {

7

8 public static void main(String[] args) {

9

10 System.out.println("現在開始初始化容器");

11

12 ApplicationContext factory = new ClassPathXmlApplicationContext("springBeanTest/beans.xml");

13 System.out.println("容器初始化成功");

14 //得到Preson,並使用

15 Person person = factory.getBean("person",Person.class);

16 System.out.println(person);

17

18 System.out.println("現在開始關閉容器!");

19 ((ClassPathXmlApplicationContext)factory).registerShutdownHook();

20 }

21 }

關閉容器使用的是實際是AbstractApplicationContext的鉤子方法。

我們來看一下結果:

現在開始初始化容器

2014-5-18 15:46:20 org.springframework.context.support.AbstractApplicationContext prepareRefresh

信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@19a0c7c: startup date [Sun May 18 15:46:20 CST 2014]; root of context hierarchy

2014-5-18 15:46:20 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions

信息: Loading XML bean definitions from class path resource [springBeanTest/beans.xml]

這是BeanFactoryPostProcessor實現類構造器!!

BeanFactoryPostProcessor調用postProcessBeanFactory方法

這是BeanPostProcessor實現類構造器!!

這是InstantiationAwareBeanPostProcessorAdapter實現類構造器!!

2014-5-18 15:46:20 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons

信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@9934d4: defining beans [beanPostProcessor,instantiationAwareBeanPostProcessor,beanFactoryPostProcessor,person]; root of factory hierarchy

InstantiationAwareBeanPostProcessor調用postProcessBeforeInstantiation方法

【構造器】調用Person的構造器實例化

InstantiationAwareBeanPostProcessor調用postProcessPropertyValues方法

【注入屬性】注入屬性address

【注入屬性】注入屬性name

【注入屬性】注入屬性phone

【BeanNameAware介面】調用BeanNameAware.setBeanName()

【BeanFactoryAware介面】調用BeanFactoryAware.setBeanFactory()

BeanPostProcessor介面方法postProcessBeforeInitialization對屬性進行更改!

【InitializingBean介面】調用InitializingBean.afterPropertiesSet()

【init-method】調用<bean>的init-method屬性指定的初始化方法

BeanPostProcessor介面方法postProcessAfterInitialization對屬性進行更改!

InstantiationAwareBeanPostProcessor調用postProcessAfterInitialization方法

容器初始化成功

Person [address=廣州, name=張三, phone=110]

現在開始關閉容器!

【DiposibleBean介面】調用DiposibleBean.destory()

【destroy-method】調用<bean>的destroy-method屬性指定的初始化方法

Spring Bean的生命周期(詳細)

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

mybatis分頁設置方法
nginx啟動、重啟、關閉

TAG:程序員小新人學習 |