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

歡迎訪問 生活随笔!

生活随笔

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

javascript

Spring bean 初始化顺序

發(fā)布時間:2023/12/4 javascript 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring bean 初始化顺序 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

InitializingBean, init-method 和 PostConstruct

1、概述

從接口的名字上不難發(fā)現(xiàn),InitializingBean 的作用就是在 bean 初始化后執(zhí)行定制化的操作。

Spring 容器中的 Bean 是有生命周期的,Spring 允許在 Bean 在初始化完成后以及 Bean 銷毀前執(zhí)行特定的操作,常用的設(shè)定方式有以下三種:

  • 通過實現(xiàn) InitializingBean/DisposableBean 接口來定制初始化之后/銷毀之前的操作方法;
  • 通過 <bean> 元素的 init-method/destroy-method 屬性指定初始化之后 /銷毀之前調(diào)用的操作方法;
  • 在指定方法上加上@PostConstruct 或@PreDestroy注解來制定該方法是在初始化之后還是銷毀之前調(diào)用。
  • 2、InitializingBean vs init-method

    接口定義如下:

    public interface InitializingBean {void afterPropertiesSet() throws Exception; }

    接口只有一個方法afterPropertiesSet,
    此方法的調(diào)用入口是負(fù)責(zé)加載 spring bean 的AbstractAutowireCapableBeanFactory,源碼如下:

    protected void invokeInitMethods(String beanName, Object bean,RootBeanDefinition mbd) throws Throwable {boolean isInitializingBean = bean instanceof InitializingBean;if ((isInitializingBean)&& (((mbd == null) || (!(mbd.isExternallyManagedInitMethod("afterPropertiesSet")))))) {if (this.logger.isDebugEnabled()) {this.logger.debug("Invoking afterPropertiesSet() on bean with name '"+ beanName + "'");}//先調(diào)用afterPropertiesSet()進行初始化if (System.getSecurityManager() != null) {try {AccessController.doPrivileged(new PrivilegedExceptionAction(bean) {public Object run() throws Exception {((InitializingBean) this.val$bean).afterPropertiesSet();return null;}}, getAccessControlContext());} catch (PrivilegedActionException pae) {throw pae.getException();}} else {((InitializingBean) bean).afterPropertiesSet();}}//然后調(diào)用InitMethod()進行初始化if (mbd != null) {String initMethodName = mbd.getInitMethodName();if ((initMethodName == null)|| ((isInitializingBean) && ("afterPropertiesSet".equals(initMethodName)))|| (mbd.isExternallyManagedInitMethod(initMethodName)))return;invokeCustomInitMethod(beanName, bean, mbd);}}

    從這段源碼可以得出以下結(jié)論:

  • spring為bean提供了兩種初始化bean的方式,實現(xiàn)InitializingBean接口,實現(xiàn)afterPropertiesSet方法,或者在配置文件中通過init-method指定,兩種方式可以同時使用
  • 實現(xiàn)InitializingBean接口是直接調(diào)用afterPropertiesSet方法,比通過反射調(diào)用init-method指定的方法效率相對來說要高點。但是init-method方式消除了對spring的依賴
  • 先調(diào)用afterPropertiesSet,再執(zhí)行 init-method 方法,如果調(diào)用afterPropertiesSet方法時出錯,則不調(diào)用init-method指定的方法
  • 3、@PostConstruct

    通過 debug 和調(diào)用棧找到類InitDestroyAnnotationBeanPostProcessor, 其中的核心方法,即 @PostConstruct 方法調(diào)用的入口:

    @Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());try {metadata.invokeInitMethods(bean, beanName);}catch (InvocationTargetException ex) {throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());}catch (Throwable ex) {throw new BeanCreationException(beanName, "Failed to invoke init method", ex);}return bean;}

    從命名上,我們就可以得到某些信息——這是一個BeanPostProcessor。BeanPostProcessor的postProcessBeforeInitialization是在Bean生命周期中afterPropertiesSet和init-method之前被調(diào)用的。另外通過跟蹤,@PostConstruct方法的調(diào)用方式也是通過反射機制。

    4、總結(jié)

  • spring bean的初始化執(zhí)行順序:構(gòu)造方法 --> @PostConstruct注解的方法 --> afterPropertiesSet方法 --> init-method指定的方法。具體可以參考例子
  • afterPropertiesSet通過接口實現(xiàn)方式調(diào)用(效率上高一點),@PostConstruct和init-method都是通過反射機制調(diào)用
  • 同理,bean銷毀過程的順序為:@PreDestroy > DisposableBean > destroy-method
    不再展開,看源碼就好

    測試代碼如下:

    @Slf4j public class InitSequenceBean implements InitializingBean {public InitSequenceBean() {log.info("InitSequenceBean: construct");}@Overridepublic void afterPropertiesSet() throws Exception {log.info("InitSequenceBean: afterPropertiesSet");}@PostConstructpublic void postConstruct() {log.info("InitSequenceBean: postConstruct");}public void initMethod() {log.info("InitSequenceBean: initMethod");} }@Configuration public class SystemConfig {@Bean(initMethod = "initMethod", name = "initSequenceBean")public InitSequenceBean initSequenceBean() {return new InitSequenceBean();} }@Slf4j public class InitSequenceBeanTest extends ApplicationTests {@Autowiredprivate InitSequenceBean initSequenceBean;@Testpublic void initSequenceBeanTest() {log.info("Finish: {}", initSequenceBean.toString());} }

    總結(jié)

    以上是生活随笔為你收集整理的Spring bean 初始化顺序的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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