亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

spring boot@EnableXXXX注解編程模型講解

 更新時間:2021年09月28日 10:29:01   作者:一擼向北  
這篇文章主要介紹了spring boot@EnableXXXX注解編程模型,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

@EnableXXXX編程模型

在spring boot中,@EnableXXX注解的功能通常是開啟某一種功能。根據(jù)某些外部配置自動裝配一些bean,來達(dá)到開啟某些功能的目的。光說很抽象,要具體分析。

@Enable模型的實現(xiàn)方式基本有3種。一個基本的@Enable注解的模型如下。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(XXXX.class)
public @interface EnableDiscoveryClient {
   /**
    * If true, the ServiceRegistry will automatically register the local server.
    */
   boolean autoRegister() default true;
}

對應(yīng)XXXX.class的不同,有3種實現(xiàn)方式。

  • 普通配置類,里面包含@Bean方法用于實例化bean
  • ImportSelector實現(xiàn)類
  • ImportBeanDefinitionRegistrar實現(xiàn)類

上面3種類都屬于@Import注解的導(dǎo)入對象,整個外部化配置過程圍繞@Import注解進(jìn)行解析,導(dǎo)入類。

@Import注解處理時機(jī)節(jié)點(@Confguration注解的類處理)

@Import注解的處理過程大致可以描述為:

  • 尋找BeanFactory中所有被@Configuration注解修飾的類,包括被@Configuration派生注解修飾的類。
  • 尋找被@Configuration注解修飾的類上的所有注解元信息(這里的搜索不僅是搜索當(dāng)前注解,還會迭代往修飾注解的注解的注解上層…..一直搜索@Import,直到注解最原始的注解),獲取@Import注解的導(dǎo)入類信息,如果沒有則不處理。
  • 根據(jù)導(dǎo)入類的信息,判定為

普通配置類,里面包含@Bean方法用于實例化bean

ImportSelector實現(xiàn)類

ImportBeanDefinitionRegistrar實現(xiàn)類

3種形式進(jìn)行處理。

從context啟動開始跟蹤主線處理代碼,調(diào)用鏈條如下。

org.springframework.context.support.AbstractApplicationContext#refresh
org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors
org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions(主線代碼,必看)
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
  //定義@Conguration注解修飾的類注冊信息列表
 List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
 String[] candidateNames = registry.getBeanDefinitionNames();
//檢查當(dāng)前context中所有的bean注冊信息
 for (String beanName : candidateNames) {
    BeanDefinition beanDef = registry.getBeanDefinition(beanName);
    if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
          ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
       if (logger.isDebugEnabled()) {
          logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
       }
    }
     //檢查class是否是@Conguration注解修飾的類,包括被“繼承”@Conguration注解的注解,例如@SpringBootConguration,具體可以跟蹤C(jī)onfigurationClassUtils.checkConfigurationClassCandidate實現(xiàn)
    else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
       configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
    }
 }
 // Return immediately if no @Configuration classes were found
 if (configCandidates.isEmpty()) {
    return;
 }
 // Sort by previously determined @Order value, if applicable
  //對配置類排序,順序由Ordered接口決定
 configCandidates.sort((bd1, bd2) -> {
    int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
    int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
    return Integer.compare(i1, i2);
 });
//......略略略
 // Parse each @Configuration class
  //處理每一個配置類
 ConfigurationClassParser parser = new ConfigurationClassParser(
       this.metadataReaderFactory, this.problemReporter, this.environment,
       this.resourceLoader, this.componentScanBeanNameGenerator, registry);
 Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
 Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
 do {
     //解析處理配置類邏輯
    parser.parse(candidates);
     //......略略略
 }
 while (!candidates.isEmpty());
//......略略略
}
org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set

ImportSelector

String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());

返回結(jié)果是所有需要導(dǎo)入的的類的全限定名。

對于全限定名數(shù)組,逐個進(jìn)行org.springframework.context.annotation.ConfigurationClassParser#processImports,相當(dāng)于循環(huán)調(diào)用processImports,把新導(dǎo)入的類也當(dāng)做@Import導(dǎo)入的類處理,如果新導(dǎo)入的類繼續(xù)導(dǎo)入新的類,就繼續(xù)org.springframework.context.annotation.ConfigurationClassParser#processImports。直到新導(dǎo)入的類不是

ImportSelector。

ImportBeanDefinitionRegistrar處理

當(dāng)@Import的類是不是ImportSelector之后,如果是ImportBeanDefinitionRegistrar,那就做BeanDefinition信息注冊到BeanFactory操作,具體實現(xiàn)在org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions實現(xiàn),在這里的處理過程是。

else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
   // Candidate class is an ImportBeanDefinitionRegistrar ->
   // delegate to it to register additional bean definitions
   Class<?> candidateClass = candidate.loadClass();
   ImportBeanDefinitionRegistrar registrar =
         BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
   ParserStrategyUtils.invokeAwareMethods(
         registrar, this.environment, this.resourceLoader, this.registry);
         //將ImportBeanDefinitionRegistrar放入map緩存起來
   configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
public void addImportBeanDefinitionRegistrar(ImportBeanDefinitionRegistrar registrar, AnnotationMetadata importingClassMetadata) {
   this.importBeanDefinitionRegistrars.put(registrar, importingClassMetadata);
}

先緩存@Import導(dǎo)入的ImportBeanDefinitionRegistrar信息,稍后統(tǒng)一調(diào)用ImportBeanDefinitionRegistrar加載注冊BeanDefinition信息。

@Configurtion注解的類處理

重復(fù)上面的整個流程,處理這個被@Configuration注解標(biāo)注的類。比較需要注意的是一般@Configuration注解標(biāo)注的類常用@Bean方式來實例化實例。這里#Bean也會解析出一個BeanMethod信息集合,稍后跟ImportBeanDefinitionRegistrar的緩存信息一樣統(tǒng)一調(diào)用然后注冊BeanDefinition。

// Process individual @Bean methods
//對配置類的@Bean方法處理邏輯
//獲取所有@Bean標(biāo)注的方法元信息,后續(xù)處理
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
   configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}

統(tǒng)一調(diào)用配置類解析出來的信息注冊BeanDefinition

在解析完配置類之后,實際還沒有進(jìn)行BeanDefinition的注冊,只得到了可以用來注冊BeanDefinition的“信息工具”,利用@Bean得到了BeanMethod,@Import(xxxImportBeanDefinitionRegistrar.class)得到了ImportBeanDefinitionRegistrar的實現(xiàn)類。最終要使用這些工具進(jìn)行BeanDefinition 信息注冊。

org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions中,當(dāng)處理完@Configuration注解的類之后就進(jìn)行ImportBeanDefinitionRegistrar的BeanDefinition注冊加載。

//處理@Configuration,遞歸尋找@Configuration,以及解析@Configuration里面的@Import、@Bean、@Component、@ImportResource等。
parser.parse(candidates);
parser.validate();
//獲取parser中解析得到的所有配置類
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
   this.reader = new ConfigurationClassBeanDefinitionReader(
         registry, this.sourceExtractor, this.resourceLoader, this.environment,
         this.importBeanNameGenerator, parser.getImportRegistry());
}
//根據(jù)遞歸找出的配置類和解析配置類得到的信息,加載BeanDefinition
this.reader.loadBeanDefinitions(configClasses);
org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitions
org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass
private void loadBeanDefinitionsForConfigurationClass(
      ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
   if (trackedConditionEvaluator.shouldSkip(configClass)) {
      String beanName = configClass.getBeanName();
      if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
         this.registry.removeBeanDefinition(beanName);
      }
      this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
      return;
   }
   if (configClass.isImported()) {
      registerBeanDefinitionForImportedConfigurationClass(configClass);
   }
   for (BeanMethod beanMethod : configClass.getBeanMethods()) {
       //利用@Bean的Method加載BeanDefinition
      loadBeanDefinitionsForBeanMethod(beanMethod);
   }
   loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
    //利用緩存的ImportBeanDefinitionRegistrar加載注冊beandefintion
   loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsFromRegistrars(以ImportBeanDefinitionRegistrar為例跟蹤)
org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(注冊BeanDefinition信息到BeanFactory)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java中Buffer緩沖區(qū)的ByteBuffer類詳解

    Java中Buffer緩沖區(qū)的ByteBuffer類詳解

    這篇文章主要介紹了Java中Buffer緩沖區(qū)的ByteBuffer類詳解,ByteBuffer類是Java NIO庫中的一個重要類,用于處理字節(jié)數(shù)據(jù),它提供了一種靈活的方式來讀取、寫入和操作字節(jié)數(shù)據(jù),ByteBuffer類是一個抽象類,可以通過靜態(tài)方法創(chuàng)建不同類型的ByteBuffer對象,需要的朋友可以參考下
    2023-10-10
  • SpringSecurity+jwt+redis基于數(shù)據(jù)庫登錄認(rèn)證的實現(xiàn)

    SpringSecurity+jwt+redis基于數(shù)據(jù)庫登錄認(rèn)證的實現(xiàn)

    本文主要介紹了SpringSecurity+jwt+redis基于數(shù)據(jù)庫登錄認(rèn)證的實現(xiàn),其中也涉及到自定義的過濾器和處理器,具有一定的參考價值,感興趣的可以了解一下
    2023-09-09
  • SpringCloud中的路由網(wǎng)關(guān)鑒權(quán)熔斷詳解

    SpringCloud中的路由網(wǎng)關(guān)鑒權(quán)熔斷詳解

    這篇文章主要介紹了SpringCloud中的路由網(wǎng)關(guān)鑒權(quán)熔斷詳解,Hystrix是一個用于處理分布式系統(tǒng)的延遲和容錯的開源庫,在分布式系統(tǒng)里,許多依賴不可避免的會調(diào)用失敗,比如超時、異常等,需要的朋友可以參考下
    2024-01-01
  • 深入理解Mybatis二級緩存

    深入理解Mybatis二級緩存

    與一級緩存相比,二級緩存范圍更大了一些,可以被多個SqlSession所共用。下面通過本文帶領(lǐng)大家一起學(xué)習(xí)mybatis二級緩存知識,一起看看吧
    2016-12-12
  • SSH框架網(wǎng)上商城項目第6戰(zhàn)之基于DataGrid的數(shù)據(jù)顯示

    SSH框架網(wǎng)上商城項目第6戰(zhàn)之基于DataGrid的數(shù)據(jù)顯示

    SSH框架網(wǎng)上商城項目第6戰(zhàn)之基于DataGrid的數(shù)據(jù)顯示,提供了豐富的選擇、排序、分組和編輯數(shù)據(jù)的功能支持,感興趣的小伙伴們可以參考一下
    2016-05-05
  • Mybatis ResultType如何處理返回類型

    Mybatis ResultType如何處理返回類型

    這篇文章主要介紹了Mybatis ResultType如何處理返回類型方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Java接口名稱沖突問題的講解

    Java接口名稱沖突問題的講解

    今天小編就為大家分享一篇關(guān)于Java接口名稱沖突問題的講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • springboot如何獲取接口下所有實現(xiàn)類

    springboot如何獲取接口下所有實現(xiàn)類

    這篇文章主要介紹了springboot如何獲取接口下所有實現(xiàn)類問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • Spring?Bean的8種加載方式總結(jié)

    Spring?Bean的8種加載方式總結(jié)

    以前學(xué)習(xí)Spring框架的時候,總結(jié)了幾種Bean的加載方式,不過老師說還有其它的加載方式,以下八種并不是全部,但也足以用來做很多事情了,希望對大家有所幫助
    2022-10-10
  • Springboot 限制IP訪問指定的網(wǎng)址實現(xiàn)

    Springboot 限制IP訪問指定的網(wǎng)址實現(xiàn)

    本文主要介紹了Springboot 限制IP訪問指定的網(wǎng)址實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-05-05

最新評論