publicvoidpostProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { intregistryId= System.identityHashCode(registry); if (this.registriesPostProcessed.contains(registryId)) { thrownewIllegalStateException( "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry); } if (this.factoriesPostProcessed.contains(registryId)) { thrownewIllegalStateException( "postProcessBeanFactory already called on this post-processor against " + registry); } this.registriesPostProcessed.add(registryId);
// Read the model and create bean definitions based on its content if (this.reader == null) { this.reader = newConfigurationClassBeanDefinitionReader( registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry()); } this.reader.loadBeanDefinitions(configClasses); alreadyParsed.addAll(configClasses);
candidates.clear(); if (registry.getBeanDefinitionCount() > candidateNames.length) { String[] newCandidateNames = registry.getBeanDefinitionNames(); Set<String> oldCandidateNames = newHashSet<>(Arrays.asList(candidateNames)); Set<String> alreadyParsedClasses = newHashSet<>(); for (ConfigurationClass configurationClass : alreadyParsed) { alreadyParsedClasses.add(configurationClass.getMetadata().getClassName()); } for (String candidateName : newCandidateNames) { if (!oldCandidateNames.contains(candidateName)) { BeanDefinitionbd= registry.getBeanDefinition(candidateName); if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) && !alreadyParsedClasses.contains(bd.getBeanClassName())) { candidates.add(newBeanDefinitionHolder(bd, candidateName)); } } } candidateNames = newCandidateNames; } } while (!candidates.isEmpty()); // 用alreadyParsed来保证不会重复注册
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) { sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry()); }
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) { // Clear cache in externally provided MetadataReaderFactory; this is a no-op // for a shared cache since it'll be cleared by the ApplicationContext. ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache(); } }
publicvoidparse(Set<BeanDefinitionHolder> configCandidates) { for (BeanDefinitionHolder holder : configCandidates) { BeanDefinitionbd= holder.getBeanDefinition(); if (bd instanceof AnnotatedBeanDefinition) { parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName()); } } this.deferredImportSelectorHandler.process(); } protectedfinalvoidparse(AnnotationMetadata metadata, String beanName)throws IOException { processConfigurationClass(newConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER); } protectedvoidprocessConfigurationClass(ConfigurationClass configClass, Predicate<String> filter)throws IOException { if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) { return; } // 没走 ConfigurationClassexistingClass=this.configurationClasses.get(configClass); if (existingClass != null) { if (configClass.isImported()) { if (existingClass.isImported()) { existingClass.mergeImportedBy(configClass); } // Otherwise ignore new imported config class; existing non-imported class overrides it. return; } else { // Explicit bean definition found, probably replacing an import. // Let's remove the old one and go with the new one. this.configurationClasses.remove(configClass); this.knownSuperclasses.values().removeIf(configClass::equals); } }
// Recursively process the configuration class and its superclass hierarchy. SourceClasssourceClass= asSourceClass(configClass, filter); do { sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter); } while (sourceClass != null);
protectedfinal SourceClass doProcessConfigurationClass( ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException { // @Configuration继承自@Component if (configClass.getMetadata().isAnnotated(Component.class.getName())) { // 内部类处理,不用关注 // Recursively process any member (nested) classes first processMemberClasses(configClass, sourceClass, filter); } // 省略以下代码 ... // @PropertySource 注解处理 // @ComponentScan 注解处理 // @Import 注解处理 // @ImportResource 注解处理
// 核心逻辑,解析为BeanMethod,并添加到configClass的beanMethods属性中 // Process individual @Bean methods Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); for (MethodMetadata methodMetadata : beanMethods) { configClass.addBeanMethod(newBeanMethod(methodMetadata, configClass)); } // 如果配置类实现了接口,要执行接口里的default方法,可忽略 // Process default methods on interfaces processInterfaces(configClass, sourceClass);
// Process superclass, if any if (sourceClass.getMetadata().hasSuperClass()) { Stringsuperclass= sourceClass.getMetadata().getSuperClassName(); if (superclass != null && !superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) { this.knownSuperclasses.put(superclass, configClass); // Superclass found, return its annotation metadata and recurse return sourceClass.getSuperClass(); } } // No superclass -> processing is complete // 结束,停止外层循环 returnnull; }
private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) { AnnotationMetadataoriginal= sourceClass.getMetadata(); // 获取被@Bean标注的方法,JVM反射方式 Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName()); // JVM返回的方法在顺序上是随机的,这里要用ASM来获取方法声明的顺序,关于ASM的两个类:ClassReader和ClassVisitor if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) { // Try reading the class file via ASM for deterministic declaration order... // Unfortunately, the JVM's standard reflection returns methods in arbitrary // order, even between different runs of the same application on the same JVM. try { AnnotationMetadataasm= this.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata(); // 通过ASM解析出来的方法列表 Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName()); if (asmMethods.size() >= beanMethods.size()) { // 注意是LinkedHashSet Set<MethodMetadata> selectedMethods = newLinkedHashSet<>(asmMethods.size()); // 两个for的作用: // 既是按asm方法列表的顺序添加,也保证了asm解析出来的方法一定在jvm解析的方法列表中,这样才能添加到返回结果中 for (MethodMetadata asmMethod : asmMethods) { for (MethodMetadata beanMethod : beanMethods) { if (beanMethod.getMethodName().equals(asmMethod.getMethodName())) { selectedMethods.add(beanMethod); break; } } } if (selectedMethods.size() == beanMethods.size()) { // All reflection-detected methods found in ASM method set -> proceed beanMethods = selectedMethods; } } } catch (IOException ex) { logger.debug("Failed to read class file via ASM for determining @Bean method order", ex); // No worries, let's continue with the reflection metadata we started with... } } return beanMethods; }
publicvoidvalidate(ProblemReporter problemReporter) { // A configuration class may not be final (CGLIB limitation) unless it declares proxyBeanMethods=false Map<String, Object> attributes = this.metadata.getAnnotationAttributes(Configuration.class.getName()); if (attributes != null && (Boolean) attributes.get("proxyBeanMethods")) { if (this.metadata.isFinal()) { problemReporter.error(newFinalConfigurationProblem()); } for (BeanMethod beanMethod : this.beanMethods) { beanMethod.validate(problemReporter); } } } publicvoidvalidate(ProblemReporter problemReporter) { // @Bean 方法如果是静态,直接算验证通过 if (getMetadata().isStatic()) { // static @Bean methods have no constraints to validate -> return immediately return; }
// 如果是private,final的方法,无法被CGLIB重写 if (this.configurationClass.getMetadata().isAnnotated(Configuration.class.getName())) { if (!getMetadata().isOverridable()) { // instance @Bean methods within @Configuration classes must be overridable to accommodate CGLIB problemReporter.error(newNonOverridableMethodError()); } } }
// 关于Bean加载的条件判断,如Spring boot中的@ConditionalOnMissingBean // Do we need to mark the bean as skipped by its condition? if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) { configClass.skippedBeanMethods.add(methodName); return; } if (configClass.skippedBeanMethods.contains(methodName)) { return; }
// Consider name and any aliases List<String> names = newArrayList<>(Arrays.asList(bean.getStringArray("name"))); // 默认用方法名作为bean name StringbeanName= (!names.isEmpty() ? names.remove(0) : methodName);
// Register aliases even when overridden // 注册别名 for (String alias : names) { this.registry.registerAlias(beanName, alias); }
// Has this effectively been overridden before (e.g. via XML)? // 是否被重复注册了 if (isOverriddenByExistingDefinition(beanMethod, beanName)) { if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) { thrownewBeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(), beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() + "' clashes with bean name for containing configuration class; please make those names unique!"); } return; }
publicvoidpostProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { intfactoryId= System.identityHashCode(beanFactory); if (this.factoriesPostProcessed.contains(factoryId)) { thrownewIllegalStateException( "postProcessBeanFactory already called on this post-processor against " + beanFactory); } this.factoriesPostProcessed.add(factoryId); if (!this.registriesPostProcessed.contains(factoryId)) { // BeanDefinitionRegistryPostProcessor hook apparently not supported... // Simply call processConfigurationClasses lazily at this point then. processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory); } enhanceConfigurationClasses(beanFactory); beanFactory.addBeanPostProcessor(newImportAwareBeanPostProcessor(beanFactory)); }
publicvoidenhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) { Map<String, AbstractBeanDefinition> configBeanDefs = newLinkedHashMap<>(); for (String beanName : beanFactory.getBeanDefinitionNames()) { BeanDefinitionbeanDef= beanFactory.getBeanDefinition(beanName); ObjectconfigClassAttr= beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE); MethodMetadatamethodMetadata=null; if (beanDef instanceof AnnotatedBeanDefinition) { methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata(); } if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) { // Configuration class (full or lite) or a configuration-derived @Bean method // -> resolve bean class at this point... AbstractBeanDefinitionabd= (AbstractBeanDefinition) beanDef; if (!abd.hasBeanClass()) { try { abd.resolveBeanClass(this.beanClassLoader); } catch (Throwable ex) { thrownewIllegalStateException( "Cannot load configuration class: " + beanDef.getBeanClassName(), ex); } } } if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) { if (!(beanDef instanceof AbstractBeanDefinition)) { thrownewBeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" + beanName + "' since it is not stored in an AbstractBeanDefinition subclass"); } elseif (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) { logger.info("Cannot enhance @Configuration bean definition '" + beanName + "' since its singleton instance has been created too early. The typical cause " + "is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " + "return type: Consider declaring such methods as 'static'."); } configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef); } } if (configBeanDefs.isEmpty()) { // nothing to enhance -> return immediately return; }
ConfigurationClassEnhancerenhancer=newConfigurationClassEnhancer(); for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) { AbstractBeanDefinitionbeanDef= entry.getValue(); // If a @Configuration class gets proxied, always proxy the target class beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE); // Set enhanced subclass of the user-specified bean class Class<?> configClass = beanDef.getBeanClass(); Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader); if (configClass != enhancedClass) { if (logger.isTraceEnabled()) { logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " + "enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName())); } beanDef.setBeanClass(enhancedClass); } } }