zoukankan      html  css  js  c++  java
  • Spring源码解析 – @Configuration配置类及注解Bean的解析

      在分析Spring 容器创建过程时,我们知道容器默认会加载一些后置处理器PostProcessor,以AnnotationConfigApplicationContext为例,在构造函数中初始化reader时,加载默认后置处理器。其中 ConfigurationClassPostProcessor这个后置处理器专门处理带有@Configuration注解的类,ConfigurationClassPostProcessor后置处理实现了BeanDefinitionRegistryPostProcessor接口和PriorityOrdered接口,所以会在容器初始化refresh()方法中执行后置处理器时优先执行,主要负责解析所有@Configuration标签类,并将Bean定义注册到容器中。

    BeanDefinitionRegistryPostProcessor解析配置类过程:

     1 public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
     2 //生成唯一标识,用于重复处理验证
     3    int registryId = System.identityHashCode(registry);
     4    if (this.registriesPostProcessed.contains(registryId)) {
     5       throw new IllegalStateException(
     6             "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
     7    }
     8    if (this.factoriesPostProcessed.contains(registryId)) {
     9       throw new IllegalStateException(
    10             "postProcessBeanFactory already called on this post-processor against " + registry);
    11    }
    12    this.registriesPostProcessed.add(registryId);
    13    //解析Java类配置bean
    14    processConfigBeanDefinitions(registry);
    15 }
    processConfigBeanDefinitions(registry)处理逻辑:
      1 public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
      2    List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
      3   //所有已经注册的bean 
      4    String[] candidateNames = registry.getBeanDefinitionNames();
      5    //遍历bean定义信息
      6    for (String beanName : candidateNames) {
      7       BeanDefinition beanDef = registry.getBeanDefinition(beanName);
      8       if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
      9             ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
     10          if (logger.isDebugEnabled()) {
     11             logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
     12          }
     13       }
     14   //如果当前的bean是Javabean配置类(含有@Configuration注解的类),则加入到集合configCandidates中,
     15       else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
     16          configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
     17       }
     18    }
     19 
     20    // Return immediately if no @Configuration classes were found
     21   // 没有@Configuration注解的类,直接退出
     22    if (configCandidates.isEmpty()) {
     23       return;
     24    }
     25 
     26    // 多个Java配置类,按@Ordered注解排序
     27    configCandidates.sort((bd1, bd2) -> {
     28       int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
     29       int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
     30       return Integer.compare(i1, i2);
     31    });
     32 
     33    // Detect any custom bean name generation strategy supplied through the enclosing application context
     34    SingletonBeanRegistry sbr = null;
     35    if (registry instanceof SingletonBeanRegistry) {
     36       sbr = (SingletonBeanRegistry) registry;
     37       if (!this.localBeanNameGeneratorSet) {
     38          BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
     39          if (generator != null) {
     40             this.componentScanBeanNameGenerator = generator;
     41             this.importBeanNameGenerator = generator;
     42          }
     43       }
     44    }
     45 
     46    if (this.environment == null) {
     47       this.environment = new StandardEnvironment();
     48    }
     49 
     50    // Parse each @Configuration class
     51   //初始化一个ConfigurationClassParser解析器,可以解析@Congiguration配置类
     52    ConfigurationClassParser parser = new ConfigurationClassParser(
     53          this.metadataReaderFactory, this.problemReporter, this.environment,
     54          this.resourceLoader, this.componentScanBeanNameGenerator, registry);
     55 
     56    Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
     57    Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
     58    do {
     59     //1.解析Java配置类
     60       parser.parse(candidates);
     61     //主要校验配置类不能使用final修饰符(CGLIB代理是生成一个子类,因此原先的类不能使用final修饰)
     62       parser.validate();
     63 
     64       //排除已处理过的配置类
     65       Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
     66       configClasses.removeAll(alreadyParsed);
     67        
     68       // Read the model and create bean definitions based on its content
     69       if (this.reader == null) {
     70          this.reader = new ConfigurationClassBeanDefinitionReader(
     71                registry, this.sourceExtractor, this.resourceLoader, this.environment,
     72                this.importBeanNameGenerator, parser.getImportRegistry());
     73       }
     74     //2.加载bean定义信息,主要实现将@Configuration @Import @ImportResource @ImportRegistrar注册为bean
     75       this.reader.loadBeanDefinitions(configClasses);
     76       alreadyParsed.addAll(configClasses);
     77       //清空已处理的配置类
     78       candidates.clear();
     79     //再次获取容器中bean定义数量  如果大于 之前获取的bean定义数量,则说明有新的bean注册到容器中,需要再次解析
     80       if (registry.getBeanDefinitionCount() > candidateNames.length) {
     81          String[] newCandidateNames = registry.getBeanDefinitionNames();
     82          Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
     83          Set<String> alreadyParsedClasses = new HashSet<>();
     84          for (ConfigurationClass configurationClass : alreadyParsed) {
     85             alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
     86          }
     87          for (String candidateName : newCandidateNames) {
     88             if (!oldCandidateNames.contains(candidateName)) {
     89                BeanDefinition bd = registry.getBeanDefinition(candidateName);
     90           //新注册的bean如果也是@Configuration配置类,则添加到数据,等待解析
     91                if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
     92                      !alreadyParsedClasses.contains(bd.getBeanClassName())) {
     93                   candidates.add(new BeanDefinitionHolder(bd, candidateName));
     94                }
     95             }
     96          }
     97          candidateNames = newCandidateNames;
     98       }
     99    }
    100    while (!candidates.isEmpty());
    101 
    102    // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
    103    if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
    104       sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
    105    }
    106 
    107    if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
    108       // Clear cache in externally provided MetadataReaderFactory; this is a no-op
    109       // for a shared cache since it'll be cleared by the ApplicationContext.
    110       ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
    111    }
    112 }

    1.解析Java配置类parser.parse(candidates)

    parser.parse(candidates)方法最终调用processConfigurationClass方法来处理@Configuration配置类,ConfigurationClassParser. processConfigurationClass()方法实现代码如下:

     1 protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
     2   //判断是否需要解析
     3    if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
     4       return;
     5    }
     6    //判断同一个配置类是否重复加载过,如果重复加载过,则合并,否则从集合中移除旧的配置类,后续逻辑将处理新的配置类
     7    ConfigurationClass existingClass = this.configurationClasses.get(configClass);
     8    if (existingClass != null) {
     9       if (configClass.isImported()) {
    10          if (existingClass.isImported()) {
    11             existingClass.mergeImportedBy(configClass);
    12          }
    13          // Otherwise ignore new imported config class; existing non-imported class overrides it.
    14          return;
    15       }
    16       else {
    17          // Explicit bean definition found, probably replacing an import.
    18          // Let's remove the old one and go with the new one.
    19          this.configurationClasses.remove(configClass);
    20          this.knownSuperclasses.values().removeIf(configClass::equals);
    21       }
    22    }
    23 
    24    // Recursively process the configuration class and its superclass hierarchy.
    25    SourceClass sourceClass = asSourceClass(configClass);
    26    do {
    27      //【真正解析配置类】
    28       sourceClass = doProcessConfigurationClass(configClass, sourceClass);
    29    }
    30    while (sourceClass != null);
    31    //再次添加到到集合中
    32    this.configurationClasses.put(configClass, configClass);
    33 }

    doProcessConfigurationClass方法主要实现从配置类中解析所有bean,包括处理内部类,父类以及各种注解

    ConfigurationClassParser. doProcessConfigurationClass()解析配置类逻辑如下:

     1 protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
     2       throws IOException {
     3 
     4    //递归处理任何成员(嵌套)类
     5    processMemberClasses(configClass, sourceClass);
     6 
     7    // 处理@PropertySource注解
     8    for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
     9          sourceClass.getMetadata(), PropertySources.class,
    10          org.springframework.context.annotation.PropertySource.class)) {
    11       if (this.environment instanceof ConfigurableEnvironment) {
    12          processPropertySource(propertySource);
    13       }
    14       else {
    15          logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
    16                "]. Reason: Environment must implement ConfigurableEnvironment");
    17       }
    18    }
    19 
    20    // 处理@ComponentScan 
    21 //获取@ComponentScan注解信息
    22    Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
    23          sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
    24    if (!componentScans.isEmpty() &&
    25          !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
    26       for (AnnotationAttributes componentScan : componentScans) {
    27 
    28          // 按@CmponentScan注解扫描bean
    29          Set<BeanDefinitionHolder> scannedBeanDefinitions =
    30                this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
    31          // 遍历扫描出的bean定义是否是配置类bean
    32          for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
    33             BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
    34             if (bdCand == null) {
    35                bdCand = holder.getBeanDefinition();
    36             }
    37 //若果扫描出的bean定义是配置类(含有@COnfiguration),则继续调用parse方法,内部再次调用doProcessConfigurationClas(),递归解析
    38             if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
    39                parse(bdCand.getBeanClassName(), holder.getBeanName());
    40             }
    41          }
    42       }
    43    }
    44 
    45    //处理@Import注解
    46    processImports(configClass, sourceClass, getImports(sourceClass), true);
    47 
    48    //处理@ImportResource注解
    49    AnnotationAttributes importResource =
    50          AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
    51    if (importResource != null) {
    52       String[] resources = importResource.getStringArray("locations");
    53       Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
    54       for (String resource : resources) {
    55          String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
    56          configClass.addImportedResource(resolvedResource, readerClass);
    57       }
    58    }
    59 
    60    //处理@Bean注解 
    61    Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
    62    for (MethodMetadata methodMetadata : beanMethods) {
    63 //将解析出的所有@Bean注解方法添加到configClass配置类信息中
    64       configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    65    }
    66 
    67    //处理接口中所有添加@Bean注解的方法,内部通过遍历所有接口,解析得到@Bean注解方法,并添加到configClass配置类信息中
    68    processInterfaces(configClass, sourceClass);
    69 
    70    // 如果有父类,则返回父类,递归执行doProcessConfigurationClass()解析父类
    71    if (sourceClass.getMetadata().hasSuperClass()) {
    72       String superclass = sourceClass.getMetadata().getSuperClassName();
    73       if (superclass != null && !superclass.startsWith("java") &&
    74             !this.knownSuperclasses.containsKey(superclass)) {
    75          this.knownSuperclasses.put(superclass, configClass);
    76          // Superclass found, return its annotation metadata and recurse
    77          return sourceClass.getSuperClass();
    78       }
    79    }
    80 
    81    // No superclass -> processing is complete
    82    return null;
    83 }

    下面看两个很重要的注解@Bean和@ComponentScan的实现过程

    @ComponentScan注解解析过程

    Set<BeanDefinitionHolder> scannedBeanDefinitions =
                   this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

    @ComponentScan注解解析,从上面的代码可以看出@ComponentScan注解解析通过调用ComponentScanAnnotationParser的parse方法完成,而parse()方法内部处理了一些scanner属性(过滤器设置)和basePackages包名处理,最终通过调用ClassPathBeanDefinitionScanner.doScan方法实现扫面工作

     1 public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
     2    ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
     3          componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
     4 
     5    Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
     6    boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
     7    scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
     8          BeanUtils.instantiateClass(generatorClass));
     9 
    10    ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
    11    if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
    12       scanner.setScopedProxyMode(scopedProxyMode);
    13    }
    14    else {
    15       Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
    16       scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
    17    }
    18 
    19    scanner.setResourcePattern(componentScan.getString("resourcePattern"));
    20 
    21    for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
    22       for (TypeFilter typeFilter : typeFiltersFor(filter)) {
    23          scanner.addIncludeFilter(typeFilter);
    24       }
    25    }
    26    for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
    27       for (TypeFilter typeFilter : typeFiltersFor(filter)) {
    28          scanner.addExcludeFilter(typeFilter);
    29       }
    30    }
    31 
    32    boolean lazyInit = componentScan.getBoolean("lazyInit");
    33    if (lazyInit) {
    34       scanner.getBeanDefinitionDefaults().setLazyInit(true);
    35    }
    36 
    37    Set<String> basePackages = new LinkedHashSet<>();
    38    String[] basePackagesArray = componentScan.getStringArray("basePackages");
    39    for (String pkg : basePackagesArray) {
    40       String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
    41             ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
    42       Collections.addAll(basePackages, tokenized);
    43    }
    44    for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
    45       basePackages.add(ClassUtils.getPackageName(clazz));
    46    }
    47    if (basePackages.isEmpty()) {
    48       basePackages.add(ClassUtils.getPackageName(declaringClass));
    49    }
    50 
    51    scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
    52       @Override
    53       protected boolean matchClassName(String className) {
    54          return declaringClass.equals(className);
    55       }
    56    });
    57    return scanner.doScan(StringUtils.toStringArray(basePackages));
    58 }
    View Code

    doScan扫描basePackages下所有bean

     1 protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
     2    Assert.notEmpty(basePackages, "At least one base package must be specified");
     3    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
     4    for (String basePackage : basePackages) {
     5     //根据basePackage加载包下所有java文件,并扫描出所有bean组件, findCandidateComponents方法内部调用ClassPathScanningCandidateComponentProvider.scanCandidateComponents(backPackages)
     6       Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
     7     //遍历beandefition
     8       for (BeanDefinition candidate : candidates) {
     9       //解析作用域Scope
    10          ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
    11          candidate.setScope(scopeMetadata.getScopeName());
    12          String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
    13 //
    14          if (candidate instanceof AbstractBeanDefinition) {
    15             postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
    16          }
    17       //通用注解解析到candidate结构中,主要是处理Lazy, primary DependsOn, Role ,Description这五个注解
    18          if (candidate instanceof AnnotatedBeanDefinition) {
    19             AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
    20          }
    21       //检查当前bean是否已经注册,不存在则注册
    22          if (checkCandidate(beanName, candidate)) {
    23             BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
    24             definitionHolder =
    25                   AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    26             beanDefinitions.add(definitionHolder);
    27         // 注册到ioc容器中,主要是一些@Component组件,@Bean注解方法并没有在此处注册, definitionHolder: beanname和beandefinition 键值对
    28             registerBeanDefinition(definitionHolder, this.registry);
    29          }
    30       }
    31    }
    32    return beanDefinitions;
    33 }

    ClassPathBeanDefinitionScanner.scanCandidateComponents实现bean定义信息扫描

     1 private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
     2    Set<BeanDefinition> candidates = new LinkedHashSet<>();
     3    try {
     4     // @ComponentScan("com.sl.springlearning.extension")包路径处理:packageSearchPath = classpath*:com/sl/springlearning/extension/**/*.class
     5       String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
     6             resolveBasePackage(basePackage) + '/' + this.resourcePattern;
     7     //获取当前包下所有的class文件
     8       Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
     9       boolean traceEnabled = logger.isTraceEnabled();
    10       boolean debugEnabled = logger.isDebugEnabled();
    11       for (Resource resource : resources) {
    12          if (traceEnabled) {
    13             logger.trace("Scanning " + resource);
    14          }
    15          if (resource.isReadable()) {
    16             try {
    17                MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
    18           //按照scanner过滤器过滤,比如配置类本身将被果过滤掉,没有@Component等组件注解的类将过滤掉
    19                if (isCandidateComponent(metadataReader)) {
    20                   ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
    21                   sbd.setResource(resource);
    22                   sbd.setSource(resource);
    23                   if (isCandidateComponent(sbd)) {
    24                      if (debugEnabled) {
    25                         logger.debug("Identified candidate component class: " + resource);
    26                      }
    27                      candidates.add(sbd);
    28                   }
    29                   else {
    30                      if (debugEnabled) {
    31                         logger.debug("Ignored because not a concrete top-level class: " + resource);
    32                      }
    33                   }
    34                }
    35                else {
    36                   if (traceEnabled) {
    37                      logger.trace("Ignored because not matching any filter: " + resource);
    38                   }
    39                }
    40             }
    41             catch (Throwable ex) {
    42                throw new BeanDefinitionStoreException(
    43                      "Failed to read candidate component class: " + resource, ex);
    44             }
    45          }
    46          else {
    47             if (traceEnabled) {
    48                logger.trace("Ignored because not readable: " + resource);
    49             }
    50          }
    51       }
    52    }
    53    catch (IOException ex) {
    54       throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
    55    }
    56    return candidates;
    57 }

    @Bean注解解析过程

    retrieveBeanMethodMetadata方法实现了@Bean方法的解析,并未将实现bean实例的创建。

     1 private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {
     2    AnnotationMetadata original = sourceClass.getMetadata();
     3 //获取所有@Bean注解的方法
     4    Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName());
     5 // 如果配置类中有多个@Bean注解的方法,则排序
     6    if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) {
     7       // Try reading the class file via ASM for deterministic declaration order...
     8       // Unfortunately, the JVM's standard reflection returns methods in arbitrary
     9       // order, even between different runs of the same application on the same JVM.
    10       try {
    11          AnnotationMetadata asm =
    12                this.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata();
    13          Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName());
    14          if (asmMethods.size() >= beanMethods.size()) {
    15             Set<MethodMetadata> selectedMethods = new LinkedHashSet<>(asmMethods.size());
    16             for (MethodMetadata asmMethod : asmMethods) {
    17                for (MethodMetadata beanMethod : beanMethods) {
    18                   if (beanMethod.getMethodName().equals(asmMethod.getMethodName())) {
    19                      selectedMethods.add(beanMethod);
    20                      break;
    21                   }
    22                }
    23             }
    24             if (selectedMethods.size() == beanMethods.size()) {
    25                // All reflection-detected methods found in ASM method set -> proceed
    26                beanMethods = selectedMethods;
    27             }
    28          }
    29       }
    30       catch (IOException ex) {
    31          logger.debug("Failed to read class file via ASM for determining @Bean method order", ex);
    32          // No worries, let's continue with the reflection metadata we started with...
    33       }
    34    }
    35    return beanMethods;
    36 }

    2.加载bean定义信息  this.reader.loadBeanDefinitions(configClasses)

      ConfigurationClassBeanDefinitionReader.loadBeanDefinitions()方法的功能就是将之前解析出的configClasses配置类信息中所有配置相关的信息添加到spring的bean定义,主要是配置类中的@Bean注解方法,配置类@ImportResource和@Import(实现ImportBeanDefinitionRegistrar接口方式)的bean注册

    ConfigurationClassBeanDefinitionReader.loadBeanDefinitions()方法 实现逻辑如下:

    1 public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
    2    TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
    3    for (ConfigurationClass configClass : configurationModel) {
    4       loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
    5    }
    6 }
     1 private void loadBeanDefinitionsForConfigurationClass(
     2       ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
     3      if (trackedConditionEvaluator.shouldSkip(configClass)) {
     4       String beanName = configClass.getBeanName();
     5       if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
     6          this.registry.removeBeanDefinition(beanName);
     7       }
     8       this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
     9       return;
    10    }
    11 
    12    if (configClass.isImported()) {
    13       registerBeanDefinitionForImportedConfigurationClass(configClass);
    14    }
    15   //将@Bean方法注册为bean
    16    for (BeanMethod beanMethod : configClass.getBeanMethods()) {
    17       loadBeanDefinitionsForBeanMethod(beanMethod);
    18    }
    19    //将configClass中中ImportResource指定的资源注册为bean
    20    loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
    21 //将configClass中ImportedRegistrar注册为bean
    22    loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
    23 }

    处理逻辑理了一遍后,看一下ConfigurationClassPostProcessor处理器解析@configuration配置类主要过程:

      1. Spring容器初始化时注册默认后置处理器ConfigurationClassPostProcessor

      2. Spring容器初始化执行refresh()方法中调用ConfigurationClassPostProcessor

      3. ConfigurationClassPostProcessor处理器借助ConfigurationClassParser完成配置类解析

      4. ConfigurationClassParser配置内解析过程中完成嵌套的MemberClass、@PropertySource注解、@ComponentScan注解(扫描package下的所有Class并进行迭代解析,主要是@Component组件解析及注册)、@ImportResource、@Bean等处理

      5. 完成@Bean注册, @ImportResource指定bean的注册以及@Import(实现ImportBeanDefinitionRegistrar接口方式)的bean注册

  • 相关阅读:
    Maven配置阿里云镜像
    docker启动报错 error creating overlay mount
    docker 运行jenkins容器
    centos7 安装docker
    Create PropertyManager Page Example (VB.NET)
    Solidworks api帮助代码报错 “特性说明符不是一个完整的语句。请使用行继续符将该特性应用于下列语句。“的解决办法!
    Solidworks API中在一个拉伸的矩形的前后面建立两个基准面的代码示例
    用vb.net运行一个应用程序,以solidworks为例
    solidworks二次开发中直接录出来的VB代码拿到自己建的项目里出现“未设置对象变量或with块变量”解决办法!
    visual studio xamarin 离线安装文件以及 android 模拟器
  • 原文地址:https://www.cnblogs.com/ashleyboy/p/9667485.html
Copyright © 2011-2022 走看看