zoukankan      html  css  js  c++  java
  • spring boot源码分析 ConfigurationClassPostProcessor

    ConfigurationClassPostProcessor实现了生成BeanDefinition的功能。

    核心方法processConfigBeanDefinitions

     1     public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
     2         List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();
     3         String[] candidateNames = registry.getBeanDefinitionNames();
     4 
     5         for (String beanName : candidateNames) {
     6             BeanDefinition beanDef = registry.getBeanDefinition(beanName);
     7             if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
     8                     ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
     9                 if (logger.isDebugEnabled()) {
    10                     logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
    11                 }
    12             }
    13             else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
    14                 configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
    15             }
    16         }
    17 
    18         // Return immediately if no @Configuration classes were found
    19         if (configCandidates.isEmpty()) {
    20             return;
    21         }
    22 
    23         // Sort by previously determined @Order value, if applicable
    24         Collections.sort(configCandidates, new Comparator<BeanDefinitionHolder>() {
    25             @Override
    26             public int compare(BeanDefinitionHolder bd1, BeanDefinitionHolder bd2) {
    27                 int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
    28                 int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
    29                 return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
    30             }
    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 && sbr.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {
    38                 BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
    39                 this.componentScanBeanNameGenerator = generator;
    40                 this.importBeanNameGenerator = generator;
    41             }
    42         }
    43 
    44         // Parse each @Configuration class
    45         ConfigurationClassParser parser = new ConfigurationClassParser(
    46                 this.metadataReaderFactory, this.problemReporter, this.environment,
    47                 this.resourceLoader, this.componentScanBeanNameGenerator, registry);
    48 
    49         Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
    50         Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
    51         do {
    52             parser.parse(candidates);
    53             parser.validate();
    54 
    55             Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(parser.getConfigurationClasses());
    56             configClasses.removeAll(alreadyParsed);
    57 
    58             // Read the model and create bean definitions based on its content
    59             if (this.reader == null) {
    60                 this.reader = new ConfigurationClassBeanDefinitionReader(
    61                         registry, this.sourceExtractor, this.resourceLoader, this.environment,
    62                         this.importBeanNameGenerator, parser.getImportRegistry());
    63             }
    64             this.reader.loadBeanDefinitions(configClasses);
    65             alreadyParsed.addAll(configClasses);
    66 
    67             candidates.clear();
    68             if (registry.getBeanDefinitionCount() > candidateNames.length) {
    69                 String[] newCandidateNames = registry.getBeanDefinitionNames();
    70                 Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames));
    71                 Set<String> alreadyParsedClasses = new HashSet<String>();
    72                 for (ConfigurationClass configurationClass : alreadyParsed) {
    73                     alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
    74                 }
    75                 for (String candidateName : newCandidateNames) {
    76                     if (!oldCandidateNames.contains(candidateName)) {
    77                         BeanDefinition bd = registry.getBeanDefinition(candidateName);
    78                         if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
    79                                 !alreadyParsedClasses.contains(bd.getBeanClassName())) {
    80                             candidates.add(new BeanDefinitionHolder(bd, candidateName));
    81                         }
    82                     }
    83                 }
    84                 candidateNames = newCandidateNames;
    85             }
    86         }
    87         while (!candidates.isEmpty());
    88 
    89         // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
    90         if (sbr != null) {
    91             if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
    92                 sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
    93             }
    94         }
    95 
    96         if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
    97             ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
    98         }
    99     }
     1     public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
     2         Assert.state(this.environment != null, "Environment must not be null");
     3         Assert.state(this.resourceLoader != null, "ResourceLoader must not be null");
     4 
     5         ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
     6                 componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
     7 
     8         Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
     9         boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
    10         scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
    11                 BeanUtils.instantiateClass(generatorClass));
    12 
    13         ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
    14         if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
    15             scanner.setScopedProxyMode(scopedProxyMode);
    16         }
    17         else {
    18             Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
    19             scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
    20         }
    21 
    22         scanner.setResourcePattern(componentScan.getString("resourcePattern"));
    23 
    24         for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
    25             for (TypeFilter typeFilter : typeFiltersFor(filter)) {
    26                 scanner.addIncludeFilter(typeFilter);
    27             }
    28         }
    29         for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
    30             for (TypeFilter typeFilter : typeFiltersFor(filter)) {
    31                 scanner.addExcludeFilter(typeFilter);
    32             }
    33         }
    34 
    35         boolean lazyInit = componentScan.getBoolean("lazyInit");
    36         if (lazyInit) {
    37             scanner.getBeanDefinitionDefaults().setLazyInit(true);
    38         }
    39 
    40         Set<String> basePackages = new LinkedHashSet<String>();
    41         String[] basePackagesArray = componentScan.getStringArray("basePackages");
    42         for (String pkg : basePackagesArray) {
    43             String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
    44                     ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
    45             basePackages.addAll(Arrays.asList(tokenized));
    46         }
    47         for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
    48             basePackages.add(ClassUtils.getPackageName(clazz));
    49         }
    50         if (basePackages.isEmpty()) {
    51             basePackages.add(ClassUtils.getPackageName(declaringClass));
    52         }
    53 
    54         scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
    55             @Override
    56             protected boolean matchClassName(String className) {
    57                 return declaringClass.equals(className);
    58             }
    59         });
    60         return scanner.doScan(StringUtils.toStringArray(basePackages));
    61     }

    上面代码可以看出ComponentScanAnnotationParser的basePackages是从启动类获取的包名。

    首先根据basePackages获取到@Component和@ManagedBean修饰的bean,然后遍历每个BeanDefinition获取里面用@Component和@ManagedBean修饰的方法,继续生成BeanDefinition。(每次获取结束后,找到已初始化的里面是否有实现了BeanDefinitionRegistryPostProcessor接口的类,如果有,则这个类作为一个Processor继续执行获取BeanDefinition,也就是我们可以实现BeanDefinitionRegistryPostProcessor这个接口去自定义Processor)

  • 相关阅读:
    CSP 模拟17
    晚测7
    CSP 模拟16
    CSP 模拟14
    CSP 模拟13
    Cypress系列(67)- 环境变量设置指南
    Cypress系列(66)- 测试运行最佳实践
    Cypress系列(65)- 测试运行失败自动重试
    Cypress系列(64)- 数据驱动策略
    Cypress系列(63)- 使用 Custom Commands
  • 原文地址:https://www.cnblogs.com/avalon-merlin/p/10552977.html
Copyright © 2011-2022 走看看