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)

posted @ 2019-03-18 16:36  Over_Watch  阅读(605)  评论(0编辑  收藏  举报