spring解析配置类

spring是如何判断一个类是否是配置类

配置类是如何注册成bd的

spring解析配置类_第1张图片

AnnotatedGenericBeanDefinition  配置类bd
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
     
   // 1. 创建BeanFactory
   // 2. 生成AnnotatedBeanDefinitionReader
   // 3. 生成ClassPathBeanDefinitionScanner
   this();

   // 利用reader把componentClasses注册为一个BeanDefinition
   register(componentClasses);

register(componentClasses); 把一个配置类解析成bd并注册到bean容器中

如何判断一个类是否是配置类

// 注意,并不是没有Configuration注解当前BeanDefinition就不是一个配置类
// 注意isConfigurationCandidate方法,会检查是否存在@Component, @ComponentScan,@Import,@ImportResource,@Bean注解
else if (config != null || isConfigurationCandidate(metadata)) {
     
   beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}

isConfigurationCandidate 的方法如下:

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 isConfigurationCandidate(AnnotationMetadata metadata) {
     
   // Do not consider an interface or an annotation...
   if (metadata.isInterface()) {
     
      return false;
   }

   // Any of the typical annotations found?
    // candidateIndicators
   for (String indicator : candidateIndicators) {
     
      if (metadata.isAnnotated(indicator)) {
     
         return true;
      }
   }

   // Finally, let's look for @Bean methods...
   try {
     
      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;
   }
}

通过上述方法判断一个类是否是配置类

找到配置类开始解析

public void parse(Set<BeanDefinitionHolder> configCandidates) {
     
   // 遍历多个配置类的BeanDefinition
   for (BeanDefinitionHolder holder : configCandidates) {
     
      BeanDefinition bd = holder.getBeanDefinition();
      try {
     
         // 处理有注解的BeanDefinition
         if (bd instanceof AnnotatedBeanDefinition) {
     
            // 处理注解的信息
            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);
      }
   }

   this.deferredImportSelectorHandler.process();
}
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
     
   // ConfigurationClass表示配置类信息,包括配置上的注解信息,和beanName,以及还有一个resource属性,表示配置类的类路径
   processConfigurationClass(new ConfigurationClass(metadata, beanName));
}
// 解析配置类
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
     
   // 解析@Conditional注解,判断是否需要解析
   if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
     
      return;
   }

   ConfigurationClass existingClass = this.configurationClasses.get(configClass);
   if (existingClass != null) {
     
      if (configClass.isImported()) {
     
         if (existingClass.isImported()) {
     
            // todo
            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 {
     
      sourceClass = doProcessConfigurationClass(configClass, sourceClass);
   }
   while (sourceClass != null);

   // 把当前配置类存在configurationClasses里面
   this.configurationClasses.put(configClass, configClass);
}
@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
      throws IOException {
     

   // 1. 如果配置bean上有@Component注解,递归去解析内部类上的注解
   if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
     
      // Recursively process any member (nested) classes first
      processMemberClasses(configClass, sourceClass);
   }

   // Process any @PropertySource annotations
   // 2. 解析@PropertySource注解
   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
   // 3. 解析@ComponentScan注解,并进行扫描
   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
         // 扫描得到BeanDefinition
         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();
            }

            // 检查扫描所得到BeanDefinition是不是配置Bean,基本上都有@Component注解,所以都是配置类
            if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
     
               parse(bdCand.getBeanClassName(), holder.getBeanName());
            }
         }
      }
   }

   // Process any @Import annotations
   // 4. 解析@Import,getImports方法返回AppConfig.class上定义的Import注解中所导入的类的信息
   processImports(configClass, sourceClass, getImports(sourceClass), true);

   // Process any @ImportResource annotations
   // 5. 解析@ImportResource,得到导入进来的spring的xml配置文件,然后解析
   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
   // 6. 解析配置类中的加了@Bean注解的方法
   Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
   for (MethodMetadata methodMetadata : beanMethods) {
     
      configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
   }

   // Process default methods on interfaces
   // 7. 如果配置类实现了某个接口,那么则解析该接口中的加了@Bean注解的默认方法
   processInterfaces(configClass, sourceClass);

   // Process superclass, if any
   // 8. 如果有父类,则返回父类给上层遍历进行处理
   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();
      }
   }

   // No superclass -> processing is complete
   return null;
}

1.处理@ComponentScan注解 (主要是通过这个注解注入大多数的业务bean)

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
     
   // 这是Spring中的Assert,大家开发时也可以用
   Assert.notEmpty(basePackages, "At least one base package must be specified");
   Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
   for (String basePackage : basePackages) {
     
      // 扫描包路径得到BeanDefinition,得到的BeanDefinition是空的,还没有解析类上所定义的注解信息
      Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
      for (BeanDefinition candidate : candidates) {
     
         // 得到Scope的信息,并设置
         ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
         candidate.setScope(scopeMetadata.getScopeName());
         // 得到beanName
         String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);

         if (candidate instanceof AbstractBeanDefinition) {
     
            // 扫描出来的bd设置默认值,进一步填充bd中的属性
            postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
         }
         if (candidate instanceof AnnotatedBeanDefinition) {
     
            AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
         }
         if (checkCandidate(beanName, candidate)) {
     
            // 生成BeanDefinitionHolder并注册到registry中
            BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
            definitionHolder =
                  AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
            beanDefinitions.add(definitionHolder);
            registerBeanDefinition(definitionHolder, this.registry);
         }
      }
   }
   return beanDefinitions;
}

spring解析配置类_第2张图片

扫描出了包添加的bd对象

说明方法是在Set candidates = findCandidateComponents(basePackage); 这里把包下面的java对象扫描进来

扫描的bd封装成ScannedGenericBeanDefinition

/**
 * Scan the class path for candidate components.
 * @param basePackage the package to check for annotated classes
 * @return a corresponding Set of autodetected bean definitions
 */
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
     
   // 扫描Component,最笨的方法就是扫描basePackage下的所有类,看是否有@Component注解
   // Spring提供了一种支持更快速扫描的机制,就是编译时直接创建一个静态的

   if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
     
      return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
   }
   else {
     
      //  得到所有的bd
      return scanCandidateComponents(basePackage);
   }
}
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
     
   // 扫描类,得到BeanDefinition
   Set<BeanDefinition> candidates = new LinkedHashSet<>();
   try {
     
      // 拼接成这种形式:classpath*:
      String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
            resolveBasePackage(basePackage) + '/' + this.resourcePattern;
      // 获取到所有的class文件封装而成的Resource对象
      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包含了对应class的元信息以及注解元信息, MetadataReader
               MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
               // 判断一个类是不是Component
               if (isCandidateComponent(metadataReader)) {
     
                  // 通过扫描@Component得到的BeanDefinition为ScannedGenericBeanDefinition
                  ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                  sbd.setResource(resource);
                  sbd.setSource(resource);
                  // 再进一步验证是不是备选的Component
                  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;
}

spring解析配置类_第3张图片

这些resource 是如何得到的 大致是遍历com.luban 下所有文件 得到的

处理@Bean

你可能感兴趣的:(spring)