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)