当前位置 : 主页 > 编程语言 > java >

SpringBoot——配置类解析

来源:互联网 收集:自由互联 发布时间:2023-02-04
全局流程解析 @Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal

全局流程解析

@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. // 这里面走进去会调用所有的BeanFactoryPostProcessor.postProcessBeanDefinitionRegistry方法 // 其中有一个是ConfigurationClassPostProcessor,这个很关键 invokeBeanFactoryPostProcessors(beanFactory); ...... } catch (BeansException ex) { ...... } finally { ...... } } } public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { int registryId = System.identityHashCode(registry); if (this.registriesPostProcessed.contains(registryId)) { throw new IllegalStateException( "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry); } if (this.factoriesPostProcessed.contains(registryId)) { throw new IllegalStateException( "postProcessBeanFactory already called on this post-processor against " + registry); } this.registriesPostProcessed.add(registryId); processConfigBeanDefinitions(registry); } ...... } public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); // 获取容器中已注册的bean名字,见后面图,注意,这里容器中这些BeanDefinition都是容器初始化过程中容器添加进去的 // 不是我们业务代码的beanDefinition String[] candidateNames = registry.getBeanDefinitionNames(); for (String beanName : candidateNames) { // 获取BeanDefinition BeanDefinition beanDef = registry.getBeanDefinition(beanName); // 判断这个BeanDefinition的configurationClass属性是不是full或者lite,如果是认为已经处理过了,第一次时默认为空, // 走下面分支 if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) || ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) { if (logger.isDebugEnabled()) { // 打印日志记录下 logger.debug("Bean definition has already been processed as a configuration class: " + beanDef); } } else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { // 1) 下面先分析下这个checkConfigurationClassCandidate方法 // 构造一个BeanDefinitionHolder,放入configCandidates中 configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); } } // Return immediately if no @Configuration classes were found if (configCandidates.isEmpty()) { return; } // Sort by previously determined @Order value, if applicable // 排序 configCandidates.sort((bd1, bd2) -> { int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); return Integer.compare(i1, i2); }); // Detect any custom bean name generation strategy supplied through the enclosing application context SingletonBeanRegistry sbr = null; // 我们传进来的registry是这个子类 if (registry instanceof SingletonBeanRegistry) { sbr = (SingletonBeanRegistry) registry; // 这边默认值false,所以会进去 if (!this.localBeanNameGeneratorSet) { BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR); // 默认是null if (generator != null) { this.componentScanBeanNameGenerator = generator; this.importBeanNameGenerator = generator; } } } // 前面已经创建过这个环境了,不为null if (this.environment == null) { this.environment = new StandardEnvironment(); } // Parse each @Configuration class // 配置类解析工具 ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); // 待处理集合 Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); // 已处理集合 Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size()); // 循环处理直到candidates.isEmpty() do { // 这边开始解析,这里在后面执行逻辑解析中分析 parser.parse(candidates); parser.validate(); Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); configClasses.removeAll(alreadyParsed); // Read the model and create bean definitions based on its content if (this.reader == null) { this.reader = new ConfigurationClassBeanDefinitionReader( 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 = new HashSet<>(Arrays.asList(candidateNames)); Set<String> alreadyParsedClasses = new HashSet<>(); for (ConfigurationClass configurationClass : alreadyParsed) { alreadyParsedClasses.add(configurationClass.getMetadata().getClassName()); } for (String candidateName : newCandidateNames) { if (!oldCandidateNames.contains(candidateName)) { BeanDefinition bd = registry.getBeanDefinition(candidateName); if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) && !alreadyParsedClasses.contains(bd.getBeanClassName())) { candidates.add(new BeanDefinitionHolder(bd, candidateName)); } } } candidateNames = newCandidateNames; } } while (!candidates.isEmpty()); // 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(); } }

点进ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)

public static boolean checkConfigurationClassCandidate( BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) { String className = beanDef.getBeanClassName(); // 获取下类名,如果类名为空或者该类为工厂类 if (className == null || beanDef.getFactoryMethodName() != null) { return false; } // 获取类的元数据信息 AnnotationMetadata metadata; // 上图的7个candidateNames中只有一个springbootApplication是AnnotatedBeanDefinition,其余全返回false if (beanDef instanceof AnnotatedBeanDefinition && className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) { // Can reuse the pre-parsed metadata from the given BeanDefinition... // springbootApplication走到这里 metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata(); } else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) { // Check already loaded Class if present... // since we possibly can't even load the class file for this Class. Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass(); metadata = new StandardAnnotationMetadata(beanClass, true); } else { try { MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className); // 读取类的元数据信息,这里面包括注解等信息 metadata = metadataReader.getAnnotationMetadata(); } catch (IOException ex) { if (logger.isDebugEnabled()) { logger.debug("Could not find class file for introspecting configuration annotations: " + className, ex); } return false; } } //点开isFullConfigurationCandidate(metadata)里面代码为return metadata.isAnnotated(Configuration.class.getName()); // metadata.isAnnotated(Configuration.class.getName()),这个就是判断类上面有没有@Configuration注解 if (isFullConfigurationCandidate(metadata)) { // 如果true的话设置下这个属性,那么就标记为处理过了 beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL); } else if (isLiteConfigurationCandidate(metadata)) { beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE); } else { // 其余6个返回false return false; } // It's a full or lite configuration candidate... Let's determine the order value, if any. Integer order = getOrder(metadata); if (order != null) { // 获取下类上的@Order信息 beanDef.setAttribute(ORDER_ATTRIBUTE, order); } return true; }

点进isLiteConfigurationCandidate(metadata)

abstract class ConfigurationClassUtils { private static final Set<String> candidateIndicators = new HashSet<>(8); static { candidateIndicators.add(Component.class.getName()); candidateIndicators.add(ComponentScan.class.getName()); candidateIndicators.add(Import.class.getName()); candidateIndicators.add(ImportResource.class.getName()); } public static boolean isLiteConfigurationCandidate(AnnotationMetadata metadata) { // Do not consider an interface or an annotation... if (metadata.isInterface()) { return false; } // Any of the typical annotations found? for (String indicator : candidateIndicators) { // 判断下类上面有没有这几个注解 if (metadata.isAnnotated(indicator)) { return true; } } // Finally, let's look for @Bean methods... try { // 判断有没有@Bean的方法 return metadata.hasAnnotatedMethods(Bean.class.getName()); } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex); } return false; } } }

执行逻辑解析

通过上面分析,已经知道了SpringBoot解析配置类的入口及大体流程,下面我们看下具体的解析过程

do { // 这里开始解析,下面先分析这个方法 parser.parse(candidates); // 校验下配置类是否有问题,不复杂,例如检测@Configuration标注的类不能是final, // @Configuration下面的@Bean标注的method必须可以复写 parser.validate(); // 构造一个configClasses集合,数据就是我们刚刚parser.parse解析到的,并去除掉已经解析过的 Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); configClasses.removeAll(alreadyParsed); // Read the model and create bean definitions based on its content // 判断reader是否为null,是的话创建一个,它是用来loadBeanDefinition的,默认是null if (this.reader == null) { this.reader = new ConfigurationClassBeanDefinitionReader( registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry()); } // 读取BeanDefinition,后面分析 this.reader.loadBeanDefinitions(configClasses); // 添加到已处理集合 alreadyParsed.addAll(configClasses); candidates.clear(); // 虽然长,但是逻辑比较简单 // 判断下容器中的BeanDefinition数量是否大于一开始的数量,什么情况下会大于?就是在解析配置类的过程中 // 有@Bean注解的方法,会引入新的BeanDefinition,这样会继续处理下新引入的这些 if (registry.getBeanDefinitionCount() > candidateNames.length) { String[] newCandidateNames = registry.getBeanDefinitionNames(); Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames)); Set<String> alreadyParsedClasses = new HashSet<>(); for (ConfigurationClass configurationClass : alreadyParsed) { alreadyParsedClasses.add(configurationClass.getMetadata().getClassName()); } for (String candidateName : newCandidateNames) { if (!oldCandidateNames.contains(candidateName)) { BeanDefinition bd = registry.getBeanDefinition(candidateName); if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) && !alreadyParsedClasses.contains(bd.getBeanClassName())) { // 判断没有处理过就加入到candidates candidates.add(new BeanDefinitionHolder(bd, candidateName)); } } } candidateNames = newCandidateNames; } } while (!candidates.isEmpty());

继续点进parser.validate()

public void validate() { for (ConfigurationClass configClass : this.configurationClasses.keySet()) { configClass.validate(this.problemReporter); } } public void validate(ProblemReporter problemReporter) { // A configuration class may not be final (CGLIB limitation) if (getMetadata().isAnnotated(Configuration.class.getName())) { if (getMetadata().isFinal()) { problemReporter.error(new FinalConfigurationProblem()); } } for (BeanMethod beanMethod : this.beanMethods) { beanMethod.validate(problemReporter); } } @Override public void validate(ProblemReporter problemReporter) { if (getMetadata().isStatic()) { // static @Bean methods have no constraints to validate -> return immediately return; } 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(new NonOverridableMethodError()); } } }

核心方法解析

parse方法

继续点进parser.parse(candidates)

//这边开始解析,下面先分析这个方法 public void parse(Set<BeanDefinitionHolder> configCandidates) { for (BeanDefinitionHolder holder : configCandidates) { // 获取BeanDefinition BeanDefinition bd = holder.getBeanDefinition(); try { if (bd instanceof AnnotatedBeanDefinition) { // 我们的SpringBootApplication会走到这边,下面先分析这边 parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName()); } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) { parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName()); } else { parse(bd.getBeanClassName(), holder.getBeanName()); } } catch (BeanDefinitionStoreException ex) { throw ex; } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex); } } // 处这边也要留意下,这边会处理@Import注解导入的配置类 this.deferredImportSelectorHandler.process(); } protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException { processConfigurationClass(new ConfigurationClass(metadata, beanName)); } protected void processConfigurationClass(ConfigurationClass configClass) throws IOException { // 根据当前类上面的@Conditional注解标注的条件判断是否要解析这个配置类 if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) { return; } // 以configClass作为key去获取,第一次来肯定是获取不到的,走下面逻辑 ConfigurationClass existingClass = 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. // 这一步其实没有做啥,重点还是看下一步骤 SourceClass sourceClass = asSourceClass(configClass); do { // 这里是重点,里面具体分为8大步骤,单独拿一小节分析 // doProcessConfigurationClass sourceClass = doProcessConfigurationClass(configClass, sourceClass); } while (sourceClass != null); // 放入configurationClasses中 this.configurationClasses.put(configClass, configClass); }

**上面的asSourceClass(configClass)最终其实就是封装了一个SourceClass对象

private SourceClass asSourceClass(ConfigurationClass configurationClass) throws IOException { AnnotationMetadata metadata = configurationClass.getMetadata(); if (metadata instanceof StandardAnnotationMetadata) { return asSourceClass(((StandardAnnotationMetadata) metadata).getIntrospectedClass()); } return asSourceClass(metadata.getClassName()); } SourceClass asSourceClass(@Nullable String className) throws IOException { if (className == null) { return new SourceClass(Object.class); } if (className.startsWith("java")) { // Never use ASM for core java types try { return new SourceClass(ClassUtils.forName(className, this.resourceLoader.getClassLoader())); } catch (ClassNotFoundException ex) { throw new NestedIOException("Failed to load class [" + className + "]", ex); } } return new SourceClass(this.metadataReaderFactory.getMetadataReader(className)); } private class SourceClass implements Ordered { private final Object source; // Class or MetadataReader private final AnnotationMetadata metadata; public SourceClass(Object source) { this.source = source; if (source instanceof Class) { this.metadata = new StandardAnnotationMetadata((Class<?>) source, true); } else { this.metadata = ((MetadataReader) source).getAnnotationMetadata(); } } }

接着点进sourceClass = doProcessConfigurationClass(configClass, sourceClass)方法

@Nullable protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) throws IOException { // 判断这个类上面有没有@Component注解 if (configClass.getMetadata().isAnnotated(Component.class.getName())) { // Recursively process any member (nested) classes first // 如果有的话,遍历其内部类,然后也是调用doProcessConfigurationClass递归处理 processMemberClasses(configClass, sourceClass); } // Process any @PropertySource annotations // 处理PropertySource注解,之前讲解属性配置也分析过,就是将该注解对应的属性文件加载到Environment中 for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) { if (this.environment instanceof ConfigurableEnvironment) { processPropertySource(propertySource); } else { logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment"); } } // Process any @ComponentScan annotations // 处理@ComponentScan注解,将其指定的包下的bean注册到框架中 Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class); if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) { for (AnnotationAttributes componentScan : componentScans) { // The config class is annotated with @ComponentScan -> perform the scan immediately Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); // Check the set of scanned definitions for any further config classes and parse recursively if needed for (BeanDefinitionHolder holder : scannedBeanDefinitions) { BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition(); if (bdCand == null) { bdCand = holder.getBeanDefinition(); } if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { parse(bdCand.getBeanClassName(), holder.getBeanName()); } } } } // Process any @Import annotations // 处理Import注解 processImports(configClass, sourceClass, getImports(sourceClass), true); // Process any @ImportResource annotations // 处理@ImportResource注解,可以通过它来指定xml文件,BeanFactory就会读取这个xml文件将bean注册进去 AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class); if (importResource != null) { String[] resources = importResource.getStringArray("locations"); Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader"); for (String resource : resources) { String resolvedResource = this.environment.resolveRequiredPlaceholders(resource); configClass.addImportedResource(resolvedResource, readerClass); } } // Process individual @Bean methods // 处理我们的类中使用@Bean注解的方法,添加到configClass的beanMethod中 Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); for (MethodMetadata methodMetadata : beanMethods) { configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); } // Process default methods on interfaces // 处理接口的默认方法,遍历这个类的接口,判断有没有使用@Bean注解的非抽象方法,添加到configClass的beanMethod中 processInterfaces(configClass, sourceClass); // Process superclass, if any // 递归处理父类,这边返回父类上层方法会递归处理 if (sourceClass.getMetadata().hasSuperClass()) { // 判断父类不为null且不在knownSuperclasses中且不以Java开头 String superclass = 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 return null; }

下面分8个步骤来解析下doProcessConfigurationClass方法

处理内部类

if (configClass.getMetadata().isAnnotated(Component.class.getName())) { // Recursively process any member (nested) classes first processMemberClasses(configClass, sourceClass); } private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass) throws IOException { Collection<SourceClass> memberClasses = sourceClass.getMemberClasses(); // 判断是否有内部类,没有的话直接不处理 if (!memberClasses.isEmpty()) { List<SourceClass> candidates = new ArrayList<>(memberClasses.size()); for (SourceClass memberClass : memberClasses) { // 判断是否是配置类,判断也很简单,之前分析过,判断类上面有没有@Configuration注解、@Import、@ImportResource // @Component、@ComponentScan以及@Bean标注的方法 if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) && !memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) { // 加入到candidates中然后排个序 candidates.add(memberClass); } } OrderComparator.sort(candidates); for (SourceClass candidate : candidates) { // 防止A引入B,B引入A if (this.importStack.contains(configClass)) { this.problemReporter.error(new CircularImportProblem(configClass, this.importStack)); } else { this.importStack.push(configClass); try { // 放入栈中并遍历处理这些配置类,也是递归处理,调用之前的doProcessConfigurationClass处理这个配置类 processConfigurationClass(candidate.asConfigClass(configClass)); } finally { this.importStack.pop(); } } } } }

处理@PropertySource注解

  • 用法:@PropertySource({"demo.properties"})
  • 遍历指定路径,替换占位符,加载资源
  • 将资源添加到environment中
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) { if (this.environment instanceof ConfigurableEnvironment) { // 这边就不进去看了,主要是读取@PropertySource注解指定的文件,将其封装成一个属性集放入到环境中 processPropertySource(propertySource); } else { logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment"); } }

处理@ComponentScan注解

  • 用法:@ComponentScan(basePackages={"pkgA","pkgB"},basePackageClasses={A.class,B.class})
  • 没设置扫描路径的话,使用配置类所在的路径
  • 过滤顺序:excludeFilters -> includeFilters -> false
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class); if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) { for (AnnotationAttributes componentScan : componentScans) { // The config class is annotated with @ComponentScan -> perform the scan immediately // 下面先分析这个parse方法 Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); // Check the set of scanned definitions for any further config classes and parse recursively if needed for (BeanDefinitionHolder holder : scannedBeanDefinitions) { BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition(); if (bdCand == null) { bdCand = holder.getBeanDefinition(); } // 如果是配置类,再递归处理 if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { parse(bdCand.getBeanClassName(), holder.getBeanName()); } } } } public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) { ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry, componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader); Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator"); boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass); // 设置一个bean名字生成器,默认就是使用org.springframework.beans.factory.support.BeanNameGenerator scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator : BeanUtils.instantiateClass(generatorClass)); // 就是默认的 ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy"); if (scopedProxyMode != ScopedProxyMode.DEFAULT) { scanner.setScopedProxyMode(scopedProxyMode); } else { Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver"); // 理解是元数据解析器 scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass)); } // 设置下扫描的资源模式,是**/*.class scanner.setResourcePattern(componentScan.getString("resourcePattern")); // 添加IncludeFilter和ExcludeFilter for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) { for (TypeFilter typeFilter : typeFiltersFor(filter)) { scanner.addIncludeFilter(typeFilter); } } for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) { for (TypeFilter typeFilter : typeFiltersFor(filter)) { scanner.addExcludeFilter(typeFilter); } } // 设置是否懒加载 boolean lazyInit = componentScan.getBoolean("lazyInit"); if (lazyInit) { scanner.getBeanDefinitionDefaults().setLazyInit(true); } // 解析扫描的包路径加入到basePackages中 Set<String> basePackages = new LinkedHashSet<>(); String[] basePackagesArray = componentScan.getStringArray("basePackages"); for (String pkg : basePackagesArray) { String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg), ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); Collections.addAll(basePackages, tokenized); } for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) { // 解析basePackageClasses所在的包并加入到basePackages basePackages.add(ClassUtils.getPackageName(clazz)); } // 如果是空的,将声明该注解所在的类的包加入到basePackages if (basePackages.isEmpty()) { // 通常我们的主配置类是没有声明包扫描的路径的,所以这里会将主配置类所在的包加到这里面 basePackages.add(ClassUtils.getPackageName(declaringClass)); } // 添加一个ExcludeFilter,跳过声明该注解的类 scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) { @Override protected boolean matchClassName(String className) { return declaringClass.equals(className); } }); return scanner.doScan(StringUtils.toStringArray(basePackages)); } protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>(); // 遍历所有的包路径 for (String basePackage : basePackages) { // 获取该包下面所有符合条件的BeanDefinition,然后遍历处理,下面会分析 Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); // 这两个if判断逻辑比较简单,就是设置一些Lazy、DependsOn属性 if (candidate instanceof AbstractBeanDefinition) { postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } // 这边是检查下有没有之前定义过这个BeanDefinition if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); // 将该beanDefinition加入到集合中,并注册到容器中 beanDefinitions.add(definitionHolder); registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; } public Set<BeanDefinition> findCandidateComponents(String basePackage) { if (this.componentsIndex != null && indexSupportsIncludeFilters()) { return addCandidateComponentsFromIndex(this.componentsIndex, basePackage); } else { return scanCandidateComponents(basePackage); } } private Set<BeanDefinition> scanCandidateComponents(String basePackage) { Set<BeanDefinition> candidates = new LinkedHashSet<>(); try { // 扫描指定包路径及其子包下面的class文件,将其封装成Resource对象 String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern; Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); for (Resource resource : resources) { if (traceEnabled) { logger.trace("Scanning " + resource); } if (resource.isReadable()) { try { MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); if (isCandidateComponent(metadataReader)) { ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setResource(resource); sbd.setSource(resource); if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Identified candidate component class: " + resource); } candidates.add(sbd); } else { if (debugEnabled) { logger.debug("Ignored because not a concrete top-level class: " + resource); } } } else { if (traceEnabled) { logger.trace("Ignored because not matching any filter: " + resource); } } } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to read candidate component class: " + resource, ex); } } else { if (traceEnabled) { logger.trace("Ignored because not readable: " + resource); } } } } catch (IOException ex) { throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); } return candidates; } // 通过之前设置的几个filter进行过滤 protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException { for (TypeFilter tf : this.excludeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return false; } } for (TypeFilter tf : this.includeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return isConditionMatch(metadataReader); } } return false; }

处理@Import注解

  • ImportSelector.class & DeferredImportSelector.class
  • 处理以上两个接口实现selectImports返回的类名数组
  • DeferredImportSelector接口调用优先级低于其他接口
  • 处理ImportBeanDefinitionRegistrar实现中注册的bean
  • 处理@Import(A.class) 点进processImports(configClass, sourceClass, getImports(sourceClass), true)
// Process any @Import annotations // getImports方法就是去递归扫描configClass上面所有的注解,将@Import注解标注的值放入importCandidates中 processImports(configClass, sourceClass, getImports(sourceClass), true); private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass, Collection<SourceClass> importCandidates, boolean checkForCircularImports) { if (importCandidates.isEmpty()) { return; } if (checkForCircularImports && isChainedImportOnStack(configClass)) { this.problemReporter.error(new CircularImportProblem(configClass, this.importStack)); } else { this.importStack.push(configClass); try { for (SourceClass candidate : importCandidates) { // 依次遍历判断类型 // 第二个是这个类型,@Import(AutoConfigurationImportSelector.class) // 这个就是自动配置原理,导入xxxAutoConfiguration这些类 if (candidate.isAssignable(ImportSelector.class)) { // Candidate class is an ImportSelector -> delegate to it to determine imports Class<?> candidateClass = candidate.loadClass(); // 实例化并调用xxxAware的方法并注入相关属性 ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class); ParserStrategyUtils.invokeAwareMethods( selector, this.environment, this.resourceLoader, this.registry); // 它是DeferredImportSelector类型的 if (selector instanceof DeferredImportSelector) { // 这边会将两个参数封装下加入到deferredImportSelectors中,后面处理 // 加入到deferredImportSelectors中后,具体的处理是在1.2.1的(**)处的 // this.deferredImportSelectorHandler.process()方法处 this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector); } else { // 不是的话获取@Import导入的类名数组 String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata()); Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames); // 然后再递归处理 processImports(configClass, currentSourceClass, importSourceClasses, false); } } // @Import(AutoConfigurationPackages.Registrar.class),我们的主配置类上面的注解就是这个类型 // 这个是用于导入主配置类所在包及其子包下的BeanDefinition else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) { // Candidate class is an ImportBeanDefinitionRegistrar -> // delegate to it to register additional bean definitions Class<?> candidateClass = candidate.loadClass(); ImportBeanDefinitionRegistrar registrar = BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class); ParserStrategyUtils.invokeAwareMethods( registrar, this.environment, this.resourceLoader, this.registry); // 这边就是将这两个参数作为key,value放入了一个map中 // this.importBeanDefinitionRegistrars.put(registrar, importingClassMetadata); configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata()); } else { // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar -> // process it as an @Configuration class this.importStack.registerImport( currentSourceClass.getMetadata(), candidate.getMetadata().getClassName()); // 当做一个普通类处理,判断是不是配置类,递归处理 processConfigurationClass(candidate.asConfigClass(configClass)); } } } catch (BeanDefinitionStoreException ex) { throw ex; } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to process import candidates for configuration class [" + configClass.getMetadata().getClassName() + "]", ex); } finally { this.importStack.pop(); } } }

处理@ImportSource注解

  • @ImportResource("A.xml")
  • 将注解属性值放入importedResources中
  • 后续loadBeanDefinitionsForConfigurationClass中加载定义的bean
// Process any @ImportResource annotations AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class); if (importResource != null) { String[] resources = importResource.getStringArray("locations"); Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader"); for (String resource : resources) { String resolvedResource = this.environment.resolveRequiredPlaceholders(resource); configClass.addImportedResource(resolvedResource, readerClass); } } final class ConfigurationClass { private final Map<String, Class<? extends BeanDefinitionReader>> importedResources = new LinkedHashMap<>(); public void addImportedResource(String importedResource, Class<? extends BeanDefinitionReader> readerClass) { // 这边就是放入到了map中 this.importedResources.put(importedResource, readerClass); } }

处理@Bean标注的方法

// Process individual @Bean methods // 获取当前类中的Bean方法 Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); for (MethodMetadata methodMetadata : beanMethods) { // 这边也是加入到set中 configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); } public void addBeanMethod(BeanMethod method) { this.beanMethods.add(method); } private final Set<BeanMethod> beanMethods = new LinkedHashSet<>();

接口默认方法处理

public interface SuperConfiguration{ @Bean("dog") default Animal getDog(){ return new Dog(); } }

接着点进processInterfaces(configClass, sourceClass)方法

// Process default methods on interfaces processInterfaces(configClass, sourceClass); /** * Register default methods on interfaces implemented by the configuration class. */ // 这边也是递归处理其父接口,判断父接口中默认方法是不是@Bean方法 private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException { for (SourceClass ifc : sourceClass.getInterfaces()) { Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(ifc); for (MethodMetadata methodMetadata : beanMethods) { if (!methodMetadata.isAbstract()) { // A default method or other concrete method on a Java 8+ interface... configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); } } processInterfaces(configClass, ifc); } }

递归处理父类

  • 1、不能为null
  • 2、全路径名不以java开头
  • 3、尚未被处理过
// Process superclass, if any if (sourceClass.getMetadata().hasSuperClass()) { String superclass = 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(); } }

参考: https://my.oschina.net/liwanghong/blog/3168003

上一篇:SpringBoot——Servlet容器启动解析
下一篇:没有了
网友评论