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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring Ioc源码分析 之 Bean的加载(7):初始化

發(fā)布時間:2025/3/15 javascript 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring Ioc源码分析 之 Bean的加载(7):初始化 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

接著分析doCreateBean()的第6步——初始化 bean 實例對象

首先回顧下CreateBean的主流程:

  • 如果是單例模式,從factoryBeanInstanceCache 緩存中獲取BeanWrapper 實例對象并刪除緩存
  • 調(diào)用 createBeanInstance() 實例化 bean
  • 后置處理
  • 單例模式的循環(huán)依賴處理
  • 屬性填充
  • 初始化 bean 實例對象
  • 依賴檢查
  • 注冊bean的銷毀方法
  • 一、初始化

    Spring在對Bean進行屬性填充之后,會對Bean進行初始化,代碼如下:

    //AbstractAutowireCapableBeanFactory.javaprotected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {//JDK的安全機制驗證權(quán)限if (System.getSecurityManager() != null) {// <1> 激活 Aware 方法,對特殊的 bean 處理:Aware、BeanClassLoaderAware、BeanFactoryAwareAccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {// <1> 激活 Aware 方法,對特殊的 bean 處理:Aware、BeanClassLoaderAware、BeanFactoryAwareinvokeAwareMethods(beanName, bean);}Object wrappedBean = bean;// <2> 后置處理器,beforeif (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}// <3> 激活用戶自定義的 init 方法try {invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}// <2> 后置處理器,afterif (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;}

    初始化 bean 的方法其實就是三個步驟的處理,而這三個步驟主要還是根據(jù)用戶設(shè)定的來進行初始化,這三個過程為:

  • <1> 激活 Aware 方法。
  • <2> 后置處理器。
  • <3> 自定義的 init 方法。
    • 1.1、Aware

    Aware ,英文翻譯是意識到的,感知的。Spring 提供了諸多 Aware 接口,用于輔助 Spring Bean 以編程的方式調(diào)用 Spring 容器,通過實現(xiàn)這些接口,可以增強 Spring Bean 的功能。

    Spring 提供了如下系列的 Aware 接口:

  • LoadTimeWeaverAware:加載Spring Bean時織入第三方模塊,如AspectJ
  • BeanClassLoaderAware:加載Spring Bean的類加載器
  • BootstrapContextAware:資源適配器BootstrapContext,如JCA,CCI
  • ResourceLoaderAware:底層訪問資源的加載器
  • BeanFactoryAware:聲明BeanFactory
  • PortletConfigAware:PortletConfig
  • PortletContextAware:PortletContext
  • ServletConfigAware:ServletConfig
  • ServletContextAware:ServletContext
  • MessageSourceAware:國際化
  • ApplicationEventPublisherAware:應(yīng)用事件
  • NotificationPublisherAware:JMX通知
  • BeanNameAware:聲明Spring Bean的名字
    • 1.2、后置處理器
      BeanPostProcessor 在前面介紹 bean 加載的過程曾多次遇到,
      它的作用是:
      如果我們想要在 Spring 容器完成 Bean 的實例化,配置和其他的初始化后添加一些自己的邏輯處理,那么請使用該接口,這個接口給與了用戶充足的權(quán)限去更改或者擴展 Spring,是我們對 Spring 進行擴展和增強處理一個必不可少的接口。
      applyBeanPostProcessorsBeforeInitialization() 方法,代碼如下:
    // AbstractAutowireCapableBeanFactory.java@Override public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;// 遍歷 BeanPostProcessor 數(shù)組for (BeanPostProcessor processor : getBeanPostProcessors()) {// 處理Object current = processor.postProcessBeforeInitialization(result, beanName);// 返回空,則返回 resultif (current == null) {return result;}// 修改 resultresult = current;}return result; }

    applyBeanPostProcessorsAfterInitialization() 方法,代碼如下:

    // AbstractAutowireCapableBeanFactory.java @Override public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;// 遍歷 BeanPostProcessorfor (BeanPostProcessor processor : getBeanPostProcessors()) {// 處理Object current = processor.postProcessAfterInitialization(result, beanName);// 返回空,則返回 resultif (current == null) {return result;}// 修改 resultresult = current;}return result; }

    其邏輯就是通過 getBeanPostProcessors() 方法,獲取定義的 BeanPostProcessor ,然后分別調(diào)用其 postProcessBeforeInitialization() 和 postProcessAfterInitialization() 方法,進行自定義的業(yè)務(wù)處理。

    • 1.3、自定義init方法
      在xml中有一個< bean >標簽的配置, init-method 方法,是可以讓我們在Bean初始化的時候,先執(zhí)行我們自定義的一些邏輯。
      其實就是在這里被觸發(fā)的,代碼如下:
    protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)throws Throwable {// 首先會檢查是否是 InitializingBean ,如果是的話需要調(diào)用 afterPropertiesSet()boolean isInitializingBean = (bean instanceof InitializingBean);if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {if (logger.isTraceEnabled()) {logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");}if (System.getSecurityManager() != null) { // 安全模式try {AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {// <1> 屬性初始化的處理((InitializingBean) bean).afterPropertiesSet();return null;}, getAccessControlContext());} catch (PrivilegedActionException pae) {throw pae.getException();}} else {// <1> 屬性初始化的處理((InitializingBean) bean).afterPropertiesSet();}}if (mbd != null && bean.getClass() != NullBean.class) {String initMethodName = mbd.getInitMethodName();if (StringUtils.hasLength(initMethodName) &&!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&!mbd.isExternallyManagedInitMethod(initMethodName)) {// <2> 激活用戶自定義的初始化方法invokeCustomInitMethod(beanName, bean, mbd);}} }

    首先,檢查是否為 InitializingBean 。如果是的話,需要執(zhí)行 afterPropertiesSet() 方法,因為我們除了可以使用 init-method 來自定初始化方法外,還可以實現(xiàn) InitializingBean 接口。接口僅有一個 afterPropertiesSet() 方法。
    兩者的執(zhí)行先后順序是先 :<1> 的 #afterPropertiesSet() 方法
    后 <2> 的 init-method 對應(yīng)的方法。

    本文轉(zhuǎn)自:https://cloud.tencent.com/developer/article/1521203

    總結(jié)

    以上是生活随笔為你收集整理的Spring Ioc源码分析 之 Bean的加载(7):初始化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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