日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring 中 Bean 的生命周期

發(fā)布時間:2025/3/21 javascript 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring 中 Bean 的生命周期 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本文作者:?伯樂在線?-?yemengying?

智商捉雞?,實(shí)在沒辦法一下子理解Spring IoC和AOP的實(shí)現(xiàn)原理,看的鬧心也不太懂,所以。。。決定拆成小的不能在小的一個個問題,一點(diǎn)點(diǎn)啃。今天先來看看Spring中Bean的生命周期。

Spring Bean是Spring應(yīng)用中最最重要的部分了。所以來看看Spring容器在初始化一個bean的時候會做那些事情,順序是怎樣的,在容器關(guān)閉的時候,又會做哪些事情。

示例代碼

git地址:https://github.com/giraffe0813/giraffeInSpring
spring版本:4.2.3.RELEASE

鑒于Spring源碼是用gradle構(gòu)建的,我也決定舍棄我大maven,嘗試下洪菊推薦過的gradle。運(yùn)行beanLifeCycle模塊下的junit test即可在控制臺看到如下輸出,可以清楚了解Spring容器在創(chuàng)建,初始化和銷毀Bean的時候依次做了那些事情。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

Spring容器初始化

=====================================

調(diào)用GiraffeService無參構(gòu)造函數(shù)

GiraffeService中利用set方法設(shè)置屬性值

調(diào)用setBeanName:: Bean Name defined in context=giraffeService

調(diào)用setBeanClassLoader,ClassLoader Name = sun.misc.Launcher$AppClassLoader

調(diào)用setBeanFactory,setBeanFactory:: giraffe bean singleton=true

調(diào)用setEnvironment

調(diào)用setResourceLoader:: Resource File Name=spring-beans.xml

調(diào)用setApplicationEventPublisher

調(diào)用setApplicationContext:: Bean Definition Names=[giraffeService, org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#0, com.giraffe.spring.service.GiraffeServicePostProcessor#0]

執(zhí)行BeanPostProcessor的postProcessBeforeInitialization方法,beanName=giraffeService

調(diào)用PostConstruct注解標(biāo)注的方法

執(zhí)行InitializingBean接口的afterPropertiesSet方法

執(zhí)行配置的init-method

執(zhí)行BeanPostProcessor的postProcessAfterInitialization方法,beanName=giraffeService

Spring容器初始化完畢

=====================================

從容器中獲取Bean

giraffe Name=李光洙

=====================================

調(diào)用preDestroy注解標(biāo)注的方法

執(zhí)行DisposableBean接口的destroy方法

執(zhí)行配置的destroy-method

Spring容器關(guān)閉

?

參考文檔

life cycle management of a spring bean
Spring Bean Life Cycle

Spring Bean的生命周期

先來看看,Spring在Bean從創(chuàng)建到銷毀的生命周期中可能做得事情。

一、initialization 和 destroy

有時我們需要在Bean屬性值set好之后和Bean銷毀之前做一些事情,比如檢查Bean中某個屬性是否被正常的設(shè)置好值了。Spring框架提供了多種方法讓我們可以在Spring Bean的生命周期中執(zhí)行initialization和pre-destroy方法。

1.實(shí)現(xiàn)InitializingBean和DisposableBean接口

這兩個接口都只包含一個方法。通過實(shí)現(xiàn)InitializingBean接口的afterPropertiesSet()方法可以在Bean屬性值設(shè)置好之后做一些操作,實(shí)現(xiàn)DisposableBean接口的destroy()方法可以在銷毀Bean之前做一些操作。

例子如下:

Java

?

1

2

3

4

5

6

7

8

9

10

11

12

public class GiraffeService implements InitializingBean,DisposableBean {

????@Override

????public void afterPropertiesSet() throws Exception {

????????System.out.println("執(zhí)行InitializingBean接口的afterPropertiesSet方法");

?

????}

?

????@Override

????public void destroy() throws Exception {

????????System.out.println("執(zhí)行DisposableBean接口的destroy方法");

????}

}

這種方法比較簡單,但是不建議使用。因?yàn)檫@樣會將Bean的實(shí)現(xiàn)和Spring框架耦合在一起。

2.在bean的配置文件中指定init-method和destroy-method方法

Spring允許我們創(chuàng)建自己的init方法和destroy方法,只要在Bean的配置文件中指定init-method和destroy-method的值就可以在Bean初始化時和銷毀之前執(zhí)行一些操作。
?如下:

Java

?

1

2

3

4

5

6

7

8

9

10

11

12

public class GiraffeService {

????//通過<bean>的destroy-method屬性指定的銷毀方法

????public void destroyMethod() throws Exception {

????????System.out.println("執(zhí)行配置的destroy-method");

????}

?

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

????public void initMethod() throws Exception {

????????System.out.println("執(zhí)行配置的init-method");

????}

?

}

?

配置文件中的配置:

Java

?

1

2

<bean name="giraffeService" class="com.giraffe.spring.service.GiraffeService" init-method="initMethod" destroy-method="destroyMethod">

</bean>

?

需要注意的是自定義的init-method和post-method方法可以拋異常但是不能有參數(shù)。
這種方式比較推薦,因?yàn)榭梢宰约簞?chuàng)建方法,無需將Bean的實(shí)現(xiàn)直接依賴于spring的框架。

3.使用@PostConstruct和@PreDestroy注解

除了xml配置的方式,Spring也支持用@PostConstruct和?@PreDestroy注解來指定init和destroy方法。這兩個注解均在javax.annotation包中。
為了注解可以生效,需要在配置文件中定義org.springframework.context.annotation.CommonAnnotationBeanPostProcessor或context:annotation-config
?如下:

Java

?

1

2

3

4

5

6

7

8

9

10

11

12

public class GiraffeService {

????@PostConstruct

????public void initPostConstruct(){

????????System.out.println("執(zhí)行PostConstruct注解標(biāo)注的方法");

????}

?

????@PreDestroy

????public void preDestroy(){

????????System.out.println("執(zhí)行preDestroy注解標(biāo)注的方法");

????}

?

}

配置文件:

Java

?

1

<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />

?

二、實(shí)現(xiàn)*Aware接口 在Bean中使用Spring框架的一些對象

有些時候我們需要在Bean的初始化中使用Spring框架自身的一些對象來執(zhí)行一些操作,比如獲取ServletContext的一些參數(shù),獲取ApplicaitionContext中的BeanDefinition的名字,獲取Bean在容器中的名字等等。為了讓Bean可以獲取到框架自身的一些對象,Spring提供了一組名為*Aware的接口。
這些接口均繼承于org.springframework.beans.factory.Aware標(biāo)記接口,并提供一個將由Bean實(shí)現(xiàn)的set*方法,Spring通過基于setter的依賴注入方式使相應(yīng)的對象可以被Bean使用。
網(wǎng)上說,這些接口是利用觀察者模式實(shí)現(xiàn)的,類似于servlet listeners,目前還不明白,不過這也不在本文的討論范圍內(nèi)。
介紹一些重要的Aware接口:

  • ApplicationContextAware: 獲得ApplicationContext對象,可以用來獲取所有Bean definition的名字。
  • BeanFactoryAware:獲得BeanFactory對象,可以用來檢測Bean的作用域。
  • BeanNameAware:獲得Bean在配置文件中定義的名字。
  • ResourceLoaderAware:獲得ResourceLoader對象,可以獲得classpath中某個文件。
  • ServletContextAware:在一個MVC應(yīng)用中可以獲取ServletContext對象,可以讀取context中的參數(shù)。
  • ServletConfigAware在一個MVC應(yīng)用中可以獲取ServletConfig對象,可以讀取config中的參數(shù)。

?如下:

Java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

public class GiraffeService implements?? ApplicationContextAware,

????????ApplicationEventPublisherAware, BeanClassLoaderAware, BeanFactoryAware,

????????BeanNameAware, EnvironmentAware, ImportAware, ResourceLoaderAware{

???????? @Override

????public void setBeanClassLoader(ClassLoader classLoader) {

????????System.out.println("執(zhí)行setBeanClassLoader,ClassLoader Name = " + classLoader.getClass().getName());

????}

?

????@Override

????public void setBeanFactory(BeanFactory beanFactory) throws BeansException {

????????System.out.println("執(zhí)行setBeanFactory,setBeanFactory:: giraffe bean singleton=" +??beanFactory.isSingleton("giraffeService"));

????}

?

????@Override

????public void setBeanName(String s) {

????????System.out.println("執(zhí)行setBeanName:: Bean Name defined in context="

????????????????+ s);

????}

?

????@Override

????public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

????????System.out.println("執(zhí)行setApplicationContext:: Bean Definition Names="

????????????????+ Arrays.toString(applicationContext.getBeanDefinitionNames()));

?

????}

?

????@Override

????public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {

????????System.out.println("執(zhí)行setApplicationEventPublisher");

????}

?

????@Override

????public void setEnvironment(Environment environment) {

????????System.out.println("執(zhí)行setEnvironment");

????}

?

????@Override

????public void setResourceLoader(ResourceLoader resourceLoader) {

?

????????Resource resource = resourceLoader.getResource("classpath:spring-beans.xml");

????????System.out.println("執(zhí)行setResourceLoader:: Resource File Name="

????????????????+ resource.getFilename());

?

????}

?

????@Override

????public void setImportMetadata(AnnotationMetadata annotationMetadata) {

????????System.out.println("執(zhí)行setImportMetadata");

????}

}

?

三、BeanPostProcessor

上面的*Aware接口是針對某個實(shí)現(xiàn)這些接口的Bean定制初始化的過程,
Spring同樣可以針對容器中的所有Bean,或者某些Bean定制初始化過程,只需提供一個實(shí)現(xiàn)BeanPostProcessor接口的類即可。 該接口中包含兩個方法,postProcessBeforeInitialization和postProcessAfterInitialization。 postProcessBeforeInitialization方法會在容器中的Bean初始化之前執(zhí)行, postProcessAfterInitialization方法在容器中的Bean初始化之后執(zhí)行。
?如下:

Java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

public class CustomerBeanPostProcessor implements BeanPostProcessor {

?

????@Override

????public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

????????System.out.println("執(zhí)行BeanPostProcessor的postProcessBeforeInitialization方法,beanName=" + beanName);

????????return bean;

????}

?

????@Override

????public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

????????System.out.println("執(zhí)行BeanPostProcessor的postProcessAfterInitialization方法,beanName=" + beanName);

????????return bean;

????}

?

?

}

要將BeanPostProcessor的Bean像其他Bean一樣定義在配置文件中

Java

?

1

<bean class="com.giraffe.spring.service.CustomerBeanPostProcessor"/>

?

總結(jié)

所以。。。結(jié)合第一節(jié)控制臺輸出的內(nèi)容,Spring Bean的生命周期是這樣紙的:

  • Bean容器找到配置文件中Spring Bean的定義。
  • Bean容器利用Java Reflection API創(chuàng)建一個Bean的實(shí)例。
  • 如果涉及到一些屬性值 利用set方法設(shè)置一些屬性值。
  • 如果Bean實(shí)現(xiàn)了BeanNameAware接口,調(diào)用setBeanName()方法,傳入Bean的名字。
  • 如果Bean實(shí)現(xiàn)了BeanClassLoaderAware接口,調(diào)用setBeanClassLoader()方法,傳入ClassLoader對象的實(shí)例。
  • 如果Bean實(shí)現(xiàn)了BeanFactoryAware接口,調(diào)用setBeanClassLoader()方法,傳入ClassLoader對象的實(shí)例。
  • 與上面的類似,如果實(shí)現(xiàn)了其他*Aware接口,就調(diào)用相應(yīng)的方法。
  • 如果有和加載這個Bean的Spring容器相關(guān)的BeanPostProcessor對象,執(zhí)行postProcessBeforeInitialization()方法
  • 如果Bean實(shí)現(xiàn)了InitializingBean接口,執(zhí)行afterPropertiesSet()方法。
  • 如果Bean在配置文件中的定義包含init-method屬性,執(zhí)行指定的方法。
  • 如果有和加載這個Bean的Spring容器相關(guān)的BeanPostProcessor對象,執(zhí)行postProcessAfterInitialization()方法
  • 當(dāng)要銷毀Bean的時候,如果Bean實(shí)現(xiàn)了DisposableBean接口,執(zhí)行destroy()方法。
  • 當(dāng)要銷毀Bean的時候,如果Bean在配置文件中的定義包含destroy-method屬性,執(zhí)行指定的方法。

總結(jié)

以上是生活随笔為你收集整理的Spring 中 Bean 的生命周期的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。