日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

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

1.概述

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

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

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

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

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

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

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

BeanDefinitionRegistryPostProcessor,BeanFactoryPostProcessor,BeanPostProcessor這三個(gè)后置處理器的調(diào)用時(shí)機(jī)都在Spring Bean生命周期中是不嚴(yán)謹(jǐn)?shù)模凑丈厦嫖覀儗ean生命周期的階段劃分,只有BeanPostProcessor作用于Bean的生命周期中,而BeanDefinitionRegistryPostProcessor,BeanFactoryPostProcessor是針對BeanDefinition的,所以不屬于Bean的生命周期中。

BeanPostProcessor在Bean生命周期的體現(xiàn)如下圖所示:

Bean的生命周期和人的一生一樣都會經(jīng)歷從出生到死亡,中間是一個(gè)漫長且復(fù)雜的過程,接下來我們就來整體分析一下Bean生命周期的核心流程和相關(guān)接口回調(diào)方法的調(diào)用時(shí)機(jī),同時(shí)這里想強(qiáng)調(diào)一下Bean的生命周期也是面試的高頻考點(diǎn),對核心流程務(wù)必要掌握清楚,這里用一張流程圖進(jìn)行詳述展示,是重點(diǎn)、重點(diǎn)、重點(diǎn)

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

Bean定義:

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

    public Boo() {
        System.out.println("boo實(shí)例化構(gòu)造方法執(zhí)行了...");
    }

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

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

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

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

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

實(shí)現(xiàn)InstantiationAwareBeanPostProcessor:

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

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

實(shí)現(xiàn)BeanPostProcessor:

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

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

執(zhí)行下面的配置類測試方法:

@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);
        }
        // 這里調(diào)用的applicationContext的close()觸發(fā)Bean的銷毀回調(diào)方法
        applicationContext.close();
    }
}

名為boo的Bean相關(guān)運(yùn)行結(jié)果如下:

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

根據(jù)控制臺打印結(jié)果可以boo的相關(guān)方法執(zhí)行順序嚴(yán)格遵從上面流程圖,同時(shí)當(dāng)我們執(zhí)行容器applicationContext的關(guān)閉方法close()會觸發(fā)調(diào)用bean的銷毀回調(diào)方法。

3.淺析Bean生命周期源碼實(shí)現(xiàn)

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

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

  // Instantiate the Bean.
  // BeanWrapper 是對 Bean 的包裝,其接口中所定義的功能很簡單包括設(shè)置獲取被包裝的對象,獲取被包裝 Bean 的屬性描述器
  BeanWrapper instanceWrapper = null;
  if (mbd.isSingleton()) {
   // <1> 單例模型,則從未完成的 FactoryBean 緩存中刪除
   instanceWrapper = this.factoryBeanInstanceCache.remove(BeanName);
  }
  if (instanceWrapper == null) {
   // <2> 使用合適的實(shí)例化策略來創(chuàng)建新的實(shí)例:工廠方法、構(gòu)造函數(shù)自動注入、簡單初始化
   instanceWrapper = createBeanInstance(BeanName, mbd, args);
  }
  // 包裝的實(shí)例對象
  Object Bean = instanceWrapper.getWrappedInstance();
  // 包裝的實(shí)例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> 解決單例模式的循環(huán)依賴
  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");
   }
   // 提前將創(chuàng)建的 Bean 實(shí)例加入到 singletonFactories 中
   // 這里是為了后期避免循環(huán)依賴
   addSingletonFactory(BeanName, () -> getEarlyBeanReference(BeanName, mbd, Bean));
  }

  // Initialize the Bean instance.
  // 開始初始化 Bean 實(shí)例對象
  Object exposedObject = Bean;
  try {
   // <5> 對 Bean 進(jìn)行填充,將各個(gè)屬性值注入,其中,可能存在依賴于其他 Bean 的屬性
   // 則會遞歸初始依賴 Bean
   populateBean(BeanName, mbd, instanceWrapper);
   // <6> 調(diào)用初始化方法
   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> 循環(huán)依賴處理
  if (earlySingletonExposure) {
   // 獲取 earlySingletonReference
   Object earlySingletonReference = getSingleton(BeanName, false);
   // 只有在存在循環(huán)依賴的情況下,earlySingletonReference 才不會為空
   if (earlySingletonReference != null) {
    // 如果 exposedObject 沒有在初始化方法中被改變,也就是沒有被增強(qiáng)
    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的創(chuàng)建過程核心步驟如下:

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

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

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 {
            // 涉及到的回調(diào)接口點(diǎn)進(jìn)去一目了然,代碼都是自解釋的
            // BeanNameAware、BeanClassLoaderAware或BeanFactoryAware
            invokeAwareMethods(BeanName, Bean);
        }

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

        try {
            // init-methods
            // 或者是實(shí)現(xiàn)了InitializingBean接口,會調(diào)用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 回調(diào)
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, BeanName);
        }
        return wrappedBean;
    }

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

4.總結(jié)

以上全部就是對Spring Bean生命周期的全面總結(jié), Spring 的 Bean 容器機(jī)制是非常強(qiáng)大的,它可以幫助我們輕松地管理 Bean 對象,并且提供了豐富的生命周期回調(diào)方法,允許我們在 Bean 的生命周期中執(zhí)行自己的特定操作,這對于我們平時(shí)工作使用中進(jìn)行增強(qiáng)擴(kuò)展至關(guān)重要,因此掌握Bean的生命周期是必須的。

分享到:
標(biāo)簽:Spring
用戶無頭像

網(wǎng)友整理

注冊時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

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

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定