|
| 1 | +ConfigurationClassPostProcessor |
| 2 | + |
| 3 | + |
| 4 | + @Override |
| 5 | + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { |
| 6 | + ... // 忽略不必要的代码 |
| 7 | + |
| 8 | + processConfigBeanDefinitions(registry); |
| 9 | + } |
| 10 | + |
| 11 | + public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { |
| 12 | + List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); |
| 13 | + // 从当前beandifinition注册表中取出所有的候选类,这里面有很多都是spring 的内置bean ,所以这些不需要处理。 |
| 14 | + String[] candidateNames = registry.getBeanDefinitionNames(); |
| 15 | + |
| 16 | + for (String beanName : candidateNames) { |
| 17 | + BeanDefinition beanDef = registry.getBeanDefinition(beanName); |
| 18 | + if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) { |
| 19 | + if (logger.isDebugEnabled()) { |
| 20 | + logger.debug("Bean definition has already been processed as a configuration class: " + beanDef); |
| 21 | + } |
| 22 | + } |
| 23 | + else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { |
| 24 | + // 将不是spring 的内置bean 取出来。这里的判断条件是有注解@Configuration 所标识的类才会被识别并添加。 |
| 25 | + configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); |
| 26 | + } |
| 27 | + } |
| 28 | + |
| 29 | + // Return immediately if no @Configuration classes were found |
| 30 | + if (configCandidates.isEmpty()) { |
| 31 | + return; |
| 32 | + } |
| 33 | + |
| 34 | + // 支持@Order 注解,以及Ordered 接口,排序能力。 |
| 35 | + // Sort by previously determined @Order value, if applicable |
| 36 | + configCandidates.sort((bd1, bd2) -> { |
| 37 | + int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); |
| 38 | + int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); |
| 39 | + return Integer.compare(i1, i2); |
| 40 | + }); |
| 41 | + |
| 42 | + // Detect any custom bean name generation strategy supplied through the enclosing application context |
| 43 | + // 是否有用户自定义的spring bean name 的生成器,如果有就取出使用。 |
| 44 | + SingletonBeanRegistry sbr = null; |
| 45 | + if (registry instanceof SingletonBeanRegistry) { |
| 46 | + sbr = (SingletonBeanRegistry) registry; |
| 47 | + if (!this.localBeanNameGeneratorSet) { |
| 48 | + BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton( |
| 49 | + AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR); |
| 50 | + if (generator != null) { |
| 51 | + this.componentScanBeanNameGenerator = generator; |
| 52 | + this.importBeanNameGenerator = generator; |
| 53 | + } |
| 54 | + } |
| 55 | + } |
| 56 | + |
| 57 | + if (this.environment == null) { |
| 58 | + this.environment = new StandardEnvironment(); |
| 59 | + } |
| 60 | + |
| 61 | + // Parse each @Configuration class |
| 62 | + // 构建出一个解析器,对前面使用@Configuration 标识的类,进行解析。 |
| 63 | + ConfigurationClassParser parser = new ConfigurationClassParser( |
| 64 | + this.metadataReaderFactory, this.problemReporter, this.environment, |
| 65 | + this.resourceLoader, this.componentScanBeanNameGenerator, registry); |
| 66 | + |
| 67 | + Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); |
| 68 | + Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size()); |
| 69 | + do { |
| 70 | + StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse"); |
| 71 | + // 解析动作,进去。 |
| 72 | + parser.parse(candidates); |
| 73 | + parser.validate(); |
| 74 | + |
| 75 | + ... // 后面的没有详细看,但核心功能不在这里面,基本都是跳过的。 |
| 76 | + } |
| 77 | + while (!candidates.isEmpty()); |
| 78 | + |
| 79 | + ... // 不太关心的代码。 |
| 80 | + } |
| 81 | + |
| 82 | + |
| 83 | +ConfigurationClassParser |
| 84 | + |
| 85 | + public void parse(Set<BeanDefinitionHolder> configCandidates) { |
| 86 | + for (BeanDefinitionHolder holder : configCandidates) { |
| 87 | + BeanDefinition bd = holder.getBeanDefinition(); |
| 88 | + try { |
| 89 | + if (bd instanceof AnnotatedBeanDefinition) { |
| 90 | + // 基本都是走的这一条分支,但是这三个分支,最终调用的都是同一个方法 processConfigurationClass(..) |
| 91 | + parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName()); |
| 92 | + } |
| 93 | + else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) { |
| 94 | + parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName()); |
| 95 | + } |
| 96 | + else { |
| 97 | + parse(bd.getBeanClassName(), holder.getBeanName()); |
| 98 | + } |
| 99 | + } |
| 100 | + catch (BeanDefinitionStoreException ex) { |
| 101 | + throw ex; |
| 102 | + } |
| 103 | + catch (Throwable ex) { |
| 104 | + throw new BeanDefinitionStoreException( |
| 105 | + "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex); |
| 106 | + } |
| 107 | + } |
| 108 | + |
| 109 | + // 这里是一个后置处理,前端的逻辑会为其填充基本数据,在这里做实际的动作。 |
| 110 | + this.deferredImportSelectorHandler.process(); |
| 111 | + } |
| 112 | + |
| 113 | + |
| 114 | + protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException { |
| 115 | + // 是否添加了@Conditional 注解,并校验。 |
| 116 | + if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) { |
| 117 | + return; |
| 118 | + } |
| 119 | + |
| 120 | + ... // 这些不关心 |
| 121 | + |
| 122 | + // Recursively process the configuration class and its superclass hierarchy. |
| 123 | + SourceClass sourceClass = asSourceClass(configClass, filter); |
| 124 | + do { |
| 125 | + // 关键在这里 |
| 126 | + sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter); |
| 127 | + } |
| 128 | + while (sourceClass != null); |
| 129 | + |
| 130 | + this.configurationClasses.put(configClass, configClass); |
| 131 | + } |
| 132 | + |
| 133 | + // 处理配置类的解析工作 |
| 134 | + protected final SourceClass doProcessConfigurationClass( |
| 135 | + ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) |
| 136 | + throws IOException { |
| 137 | + |
| 138 | + if (configClass.getMetadata().isAnnotated(Component.class.getName())) { |
| 139 | + // Recursively process any member (nested) classes first |
| 140 | + // 这里并不重要,因为基本没人这么实现 |
| 141 | + // 它会检查当前类里面的内部类,对该内部类也要进行解析。 |
| 142 | + // 如果有,那最终也会在某个位置递归到当前方法来的。 |
| 143 | + processMemberClasses(configClass, sourceClass, filter); |
| 144 | + } |
| 145 | + |
| 146 | + // Process any @PropertySource annotations |
| 147 | + // 对存在注解@PropertySource 的类进行解析,并处理对应的逻辑 |
| 148 | + for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable( |
| 149 | + sourceClass.getMetadata(), PropertySources.class, |
| 150 | + org.springframework.context.annotation.PropertySource.class)) { |
| 151 | + if (this.environment instanceof ConfigurableEnvironment) { |
| 152 | + processPropertySource(propertySource); |
| 153 | + } |
| 154 | + else { |
| 155 | + logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + |
| 156 | + "]. Reason: Environment must implement ConfigurableEnvironment"); |
| 157 | + } |
| 158 | + } |
| 159 | + |
| 160 | + // Process any @ComponentScan annotations |
| 161 | + // 对存在注解@ComponentScan 的类进行解析,并处理对应的逻辑 |
| 162 | + // 对于spring-boot 应用这里是很关键的一点,@SpringBootApplication 的解析,这里就是入口。 |
| 163 | + Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable( |
| 164 | + sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class); |
| 165 | + if (!componentScans.isEmpty() && |
| 166 | + !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) { |
| 167 | + for (AnnotationAttributes componentScan : componentScans) { |
| 168 | + // The config class is annotated with @ComponentScan -> perform the scan immediately |
| 169 | + // 这里将对应的扫描包路径下面的所有被识别为Bean 的Class 都解析出来,并将其相关的信息封闭到BeanDefinition 中,最终包装到BeanDefinitionHolder 中。 |
| 170 | + Set<BeanDefinitionHolder> scannedBeanDefinitions = |
| 171 | + this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); |
| 172 | + // Check the set of scanned definitions for any further config classes and parse recursively if needed |
| 173 | + for (BeanDefinitionHolder holder : scannedBeanDefinitions) { |
| 174 | + BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition(); |
| 175 | + if (bdCand == null) { |
| 176 | + bdCand = holder.getBeanDefinition(); |
| 177 | + } |
| 178 | + // 如果对应的Class 被注解@Configuration 标识,那么会递归调用 parse(..) 方法,继续处理。 |
| 179 | + // 我们要知道:当前方法也是从某个 parse(..) 方法调用进来的。 |
| 180 | + if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { |
| 181 | + parse(bdCand.getBeanClassName(), holder.getBeanName()); |
| 182 | + } |
| 183 | + } |
| 184 | + } |
| 185 | + } |
| 186 | + |
| 187 | + // Process any @Import annotations |
| 188 | + // 处理@Import 注解 |
| 189 | + processImports(configClass, sourceClass, getImports(sourceClass), filter, true); |
| 190 | + |
| 191 | + // Process any @ImportResource annotations |
| 192 | + // 处理@ImportResource 注解 |
| 193 | + AnnotationAttributes importResource = |
| 194 | + AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class); |
| 195 | + if (importResource != null) { |
| 196 | + String[] resources = importResource.getStringArray("locations"); |
| 197 | + Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader"); |
| 198 | + for (String resource : resources) { |
| 199 | + String resolvedResource = this.environment.resolveRequiredPlaceholders(resource); |
| 200 | + configClass.addImportedResource(resolvedResource, readerClass); |
| 201 | + } |
| 202 | + } |
| 203 | + |
| 204 | + // Process individual @Bean methods |
| 205 | + // 对@Bean 注解标注的方法的处理 |
| 206 | + Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); |
| 207 | + for (MethodMetadata methodMetadata : beanMethods) { |
| 208 | + configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); |
| 209 | + } |
| 210 | + |
| 211 | + // Process default methods on interfaces |
| 212 | + // 对于jdk 1.8 之后,接口上面也有默认方法的实现,对这些方法的处理。 |
| 213 | + processInterfaces(configClass, sourceClass); |
| 214 | + |
| 215 | + // Process superclass, if any |
| 216 | + // 处理父类的 |
| 217 | + if (sourceClass.getMetadata().hasSuperClass()) { |
| 218 | + String superclass = sourceClass.getMetadata().getSuperClassName(); |
| 219 | + if (superclass != null && !superclass.startsWith("java") && |
| 220 | + !this.knownSuperclasses.containsKey(superclass)) { |
| 221 | + this.knownSuperclasses.put(superclass, configClass); |
| 222 | + // Superclass found, return its annotation metadata and recurse |
| 223 | + return sourceClass.getSuperClass(); |
| 224 | + } |
| 225 | + } |
| 226 | + |
| 227 | + // No superclass -> processing is complete |
| 228 | + return null; |
| 229 | + } |
0 commit comments