亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.430618.com 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

1.概述

首先Bean就是一些JAVA對象,只不過這些Bean不是我們主動new出來的,而是交個Spring IOC容器創建并管理的,因此Bean的生命周期受Spring IOC容器控制,Bean生命周期大致分為以下幾個階段:

  • Bean的實例化(Instantiation):Spring框架會取出BeanDefinition的信息進行判斷當前Bean的范圍是否是singleton的,是否不是延遲加載的,是否不是FactoryBean等,最終將一個普通的singleton的Bean通過反射進行實例化

  • Bean的屬性賦值(Populate):Bean實例化之后還僅僅是個"半成品",還需要對Bean實例的屬性進行填充,Bean的屬性賦值就是指 Spring 容器根據BeanDefinition中屬性配置的屬性值注入到 Bean 對象中的過程。

  • Bean的初始化(Initialization):對Bean實例的屬性進行填充完之后還需要執行一些Aware接口方法、執行BeanPostProcessor方法、執行InitializingBean接口的初始化方法、執行自定義初始化init方法等。該階段是Spring最具技術含量和復雜度的階段,并且Spring高頻面試題Bean的循環引用問題也是在這個階段體現的;

  • Bean的使用階段:經過初始化階段,Bean就成為了一個完整的Spring Bean,被存儲到單例池singletonObjects中去了,即完成了Spring Bean的整個生命周期,接下來Bean就可以被隨心所欲地使用了。

  • Bean的銷毀(Destruction):Bean 的銷毀是指 Spring 容器在關閉時,執行一些清理操作的過程。在 Spring 容器中, Bean 的銷毀方式有兩種:銷毀方法destroy-method和 DisposableBean 接口。

2.Bean生命周期詳解和使用案例

BeanDefinitionRegistryPostProcessor,BeanFactoryPostProcessor,BeanPostProcessor這三個后置處理器的調用時機都在Spring Bean生命周期中是不嚴謹的,按照上面我們對Bean生命周期的階段劃分,只有BeanPostProcessor作用于Bean的生命周期中,而BeanDefinitionRegistryPostProcessor,BeanFactoryPostProcessor是針對BeanDefinition的,所以不屬于Bean的生命周期中。

BeanPostProcessor在Bean生命周期的體現如下圖所示:

Bean的生命周期和人的一生一樣都會經歷從出生到死亡,中間是一個漫長且復雜的過程,接下來我們就來整體分析一下Bean生命周期的核心流程和相關接口回調方法的調用時機,同時這里想強調一下Bean的生命周期也是面試的高頻考點,對核心流程務必要掌握清楚,這里用一張流程圖進行詳述展示,是重點、重點、重點

根據上面的Bean生命周期核心流程做如下代碼演示示例:

Bean定義:

@Data
@AllArgsConstructor
public class Boo implements InitializingBean, DisposableBean, BeanNameAware {
    private Long id;
    private String name;

    public Boo() {
        System.out.println("boo實例化構造方法執行了...");
    }

    @PostConstruct
    public void initMethod() {
        System.out.println("boo執行初始化init()方法了...");
    }

    @PreDestroy
    public void destroyMethod() {
        System.out.println("boo執行初始化destroy()方法了...");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("boo執行InitializingBean的afterPropertiesSet()方法了...");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("boo執行DisposableBean的destroy()方法了...");
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("boo執行BeanNameAware的setBeanName()方法了...");
    }
}

實現InstantiationAwareBeanPostProcessor:

@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> BeanClass, String BeanName) throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor的before()執行了...." + BeanName);
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object Bean, String BeanName) throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor的after()執行了...." + BeanName);
        return false;
    }
}

實現BeanPostProcessor:

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object Bean, String BeanName) throws BeansException {
        System.out.println("BeanPostProcessor的before()執行了...." + BeanName);
        return Bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object Bean, String BeanName) throws BeansException {
        System.out.println("BeanPostProcessor的after()執行了...."+ BeanName);
        return Bean;
    }
}

執行下面的配置類測試方法:

@ComponentScan(basePackages = {"com.shepherd.common.config"})
@Configuration
public class MyConfig {

    @Bean
    public Boo boo() {
        return new Boo();
    }

    public static void mAIn(String[] args) {

        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        String[] BeanDefinitionNames = applicationContext.getBeanDefinitionNames();
        // 遍歷Spring容器中的BeanName
        for (String BeanDefinitionName : BeanDefinitionNames) {
            System.out.println(BeanDefinitionName);
        }
        // 這里調用的applicationContext的close()觸發Bean的銷毀回調方法
        applicationContext.close();
    }
}

名為boo的Bean相關運行結果如下:

InstantiationAwareBeanPostProcessor的before()執行了....boo
boo實例化構造方法執行了...
InstantiationAwareBeanPostProcessor的after()執行了....boo
boo執行BeanNameAware的setBeanName()方法了...
BeanPostProcessor的before()執行了....boo
boo執行初始化init()方法了...
boo執行InitializingBean的afterPropertiesSet()方法了...
BeanPostProcessor的after()執行了....boo
......
boo執行初始化destroy()方法了...
boo執行DisposableBean的destroy()方法了...

根據控制臺打印結果可以boo的相關方法執行順序嚴格遵從上面流程圖,同時當我們執行容器applicationContext的關閉方法close()會觸發調用bean的銷毀回調方法。

3.淺析Bean生命周期源碼實現

DefaultListableBeanFactory是Spring IOC的Bean工廠的一個默認實現,IOC大部分核心邏輯實現都在這里,可關注。Bean生命周期就是創建Bean的過程,這里我們就不在拐彎抹角兜圈子,直接來到DefaultListableBeanFactory繼承的AbstractAutowireCapableBeanFactory#doCreateBean()方法,之前說過在Spring框架中以do開頭的方法都是核心邏輯實現所在

protected Object doCreateBean(String BeanName, RootBeanDefinition mbd, @Nullable Object[] args)
   throws BeanCreationException {

  // Instantiate the Bean.
  // BeanWrapper 是對 Bean 的包裝,其接口中所定義的功能很簡單包括設置獲取被包裝的對象,獲取被包裝 Bean 的屬性描述器
  BeanWrapper instanceWrapper = null;
  if (mbd.isSingleton()) {
   // <1> 單例模型,則從未完成的 FactoryBean 緩存中刪除
   instanceWrapper = this.factoryBeanInstanceCache.remove(BeanName);
  }
  if (instanceWrapper == null) {
   // <2> 使用合適的實例化策略來創建新的實例:工廠方法、構造函數自動注入、簡單初始化
   instanceWrapper = createBeanInstance(BeanName, mbd, args);
  }
  // 包裝的實例對象
  Object Bean = instanceWrapper.getWrappedInstance();
  // 包裝的實例class類型
  Class<?> BeanType = instanceWrapper.getWrappedClass();
  if (BeanType != NullBean.class) {
   mbd.resolvedTargetType = BeanType;
  }

  // Allow post-processors to modify the merged Bean definition.
  // <3> 判斷是否有后置處理
  // 如果有后置處理,則允許后置處理修改 BeanDefinition
  synchronized (mbd.postProcessingLock) {
   if (!mbd.postProcessed) {
    try {
     applyMergedBeanDefinitionPostProcessors(mbd, BeanType, BeanName);
    }
    catch (Throwable ex) {
     throw new BeanCreationException(mbd.getResourceDescription(), BeanName,
       "Post-processing of merged Bean definition failed", ex);
    }
    mbd.postProcessed = true;
   }
  }

  // Eagerly cache singletons to be able to resolve circular references
  // even when triggered by lifecycle interfaces like BeanFactoryAware.
  // <4> 解決單例模式的循環依賴
  boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
    isSingletonCurrentlyInCreation(BeanName));
  if (earlySingletonExposure) {
   if (logger.isTraceEnabled()) {
    logger.trace("Eagerly caching Bean '" + BeanName +
      "' to allow for resolving potential circular references");
   }
   // 提前將創建的 Bean 實例加入到 singletonFactories 中
   // 這里是為了后期避免循環依賴
   addSingletonFactory(BeanName, () -> getEarlyBeanReference(BeanName, mbd, Bean));
  }

  // Initialize the Bean instance.
  // 開始初始化 Bean 實例對象
  Object exposedObject = Bean;
  try {
   // <5> 對 Bean 進行填充,將各個屬性值注入,其中,可能存在依賴于其他 Bean 的屬性
   // 則會遞歸初始依賴 Bean
   populateBean(BeanName, mbd, instanceWrapper);
   // <6> 調用初始化方法
   exposedObject = initializeBean(BeanName, exposedObject, mbd);
  }
  catch (Throwable ex) {
   if (ex instanceof BeanCreationException && BeanName.equals(((BeanCreationException) ex).getBeanName())) {
    throw (BeanCreationException) ex;
   }
   else {
    throw new BeanCreationException(
      mbd.getResourceDescription(), BeanName, "Initialization of Bean failed", ex);
   }
  }

  // <7> 循環依賴處理
  if (earlySingletonExposure) {
   // 獲取 earlySingletonReference
   Object earlySingletonReference = getSingleton(BeanName, false);
   // 只有在存在循環依賴的情況下,earlySingletonReference 才不會為空
   if (earlySingletonReference != null) {
    // 如果 exposedObject 沒有在初始化方法中被改變,也就是沒有被增強
    if (exposedObject == Bean) {
     exposedObject = earlySingletonReference;
    }
    // 處理依賴
    else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(BeanName)) {
     String[] dependentBeans = getDependentBeans(BeanName);
     Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
     for (String dependentBean : dependentBeans) {
      if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
       actualDependentBeans.add(dependentBean);
      }
     }
     if (!actualDependentBeans.isEmpty()) {
      throw new BeanCurrentlyInCreationException(BeanName,
        "Bean with name '" + BeanName + "' has been injected into other Beans [" +
        StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
        "] in its raw version as part of a circular reference, but has eventually been " +
        "wrapped. This means that said other Beans do not use the final version of the " +
        "Bean. This is often the result of over-eager type matching - consider using " +
        "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
     }
    }
   }
  }

  // Register Bean as disposable.
  try {
   // <8> 注冊 Bean的銷毀邏輯
   registerDisposableBeanIfNecessary(BeanName, Bean, mbd);
  }
  catch (BeanDefinitionValidationException ex) {
   throw new BeanCreationException(
     mbd.getResourceDescription(), BeanName, "Invalid destruction signature", ex);
  }

  return exposedObject;
 }

由上面代碼可知,Bean的創建過程核心步驟如下:

  • createBeanInstance(BeanName, mbd, args) 進行Bean的實例化
  • populateBean(BeanName, mbd, instanceWrapper)進行Bean的屬性填充賦值
  • initializeBean(BeanName, exposedObject, mbd)處理Bean初始化之后的各種回調事件
  • registerDisposableBeanIfNecessary(BeanName, Bean, mbd)注冊Bean的銷毀接口
  • 解決創建Bean過程中的循環依賴,Spring使用三級緩存解決循環依賴,這也是一個重要的知識點,這里不詳細闡述,后面會安排

接下來我們就來看看和Bean初始化階段相關各種回調事件執行方法#initializeBean(),分析一下上面流程圖的執行順序是怎么實現的。

protected Object initializeBean(final String BeanName, final Object Bean, RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    invokeAwareMethods(BeanName, Bean);
                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            // 涉及到的回調接口點進去一目了然,代碼都是自解釋的
            // BeanNameAware、BeanClassLoaderAware或BeanFactoryAware
            invokeAwareMethods(BeanName, Bean);
        }

        Object wrappedBean = Bean;
        if (mbd == null || !mbd.isSynthetic()) {
            // BeanPostProcessor 的 postProcessBeforeInitialization 回調
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, BeanName);
        }

        try {
            // init-methods
            // 或者是實現了InitializingBean接口,會調用afterPropertiesSet() 方法
            invokeInitMethods(BeanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    BeanName, "Invocation of init method failed", ex);
        }
        if (mbd == null || !mbd.isSynthetic()) {
            // BeanPostProcessor 的 postProcessAfterInitialization 回調
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, BeanName);
        }
        return wrappedBean;
    }

至于Bean的銷毀流程與Bean初始化類似,從上面的使用示例中看可以得出當容器關閉時,才會對Bean銷毀方法進行調用。銷毀過程是這樣的。順著close()-> doClose() -> destroyBeans() -> destroySingletons() -> destroySingleton() -> destroyBean() -> Bean.destroy() ,會看到最終調用Bean的銷毀方法。這里就不在展示源碼細節啦,有興趣的話自行去調試查看了解

4.總結

以上全部就是對Spring Bean生命周期的全面總結, Spring 的 Bean 容器機制是非常強大的,它可以幫助我們輕松地管理 Bean 對象,并且提供了豐富的生命周期回調方法,允許我們在 Bean 的生命周期中執行自己的特定操作,這對于我們平時工作使用中進行增強擴展至關重要,因此掌握Bean的生命周期是必須的。

分享到:
標簽:Spring
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定