Spring源码 --- ScannedGenericBeanDefinition的初始化使用过程

ScannedGenericBeanDefinition的初始化使用过程主要是在ConfigurationClassParser类中进行对应处理的。这里我们先通过一个demo查看其流程:
@Test
public void testComponents() throws Exception {
   ConfigurationClassParser configurationClassParser = new ConfigurationClassParser(
         new CachingMetadataReaderFactory(),
         new FailFastProblemReporter(),
         new StandardEnvironment(),
         new DefaultResourceLoader(),
         new AnnotationBeanNameGenerator(),
         new DefaultListableBeanFactory());
   configurationClassParser.parse(loadAsConfigurationSource(ComponentObj.class), "componentObj");
}
protected String loadAsConfigurationSource(Class<?> clazz) throws Exception {
   return clazz.getName();
}
@ComponentScan(basePackages = {"fev"})
class ComponentObj
{
}
protected final void parse(@Nullable String className, String beanName) throws IOException {
   Assert.notNull(className, "No bean class name for configuration class bean definition");
   MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
   processConfigurationClass(new ConfigurationClass(reader, beanName));
}
public ConfigurationClass(MetadataReader metadataReader, String beanName) {
   Assert.notNull(beanName, "Bean name must not be null");
   this.metadata = metadataReader.getAnnotationMetadata();
   this.resource = metadataReader.getResource();
   this.beanName = beanName;
}
final class ConfigurationClass {
   private final AnnotationMetadata metadata;
   private final Resource resource;
   @Nullable
   private String beanName;
    .............
}

这里的MetadataReader与ConfigurationClass都是去描叙这个class的内容的。

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
   if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
      return;
   }
   ConfigurationClass existingClass = this.configurationClasses.get(configClass);
   if (existingClass != null) {
      ...........
   }
   // Recursively process the configuration class and its superclass hierarchy.
   SourceClass sourceClass = asSourceClass(configClass);
   do {
      sourceClass = doProcessConfigurationClass(configClass, sourceClass);
   }
   while (sourceClass != null);
   this.configurationClasses.put(configClass, configClass);
}

然后这里的this.conditionEvaluator.shouldSkip方法的调用,在前一章已经讲过,其是看当前class有没有注解Condition进行对应match判断处理。

往下,可以看到这里是用来一个map去做缓存处理,SourceClass:

private class SourceClass implements Ordered {
   private final Object source;  // Class or MetadataReader
   private final AnnotationMetadata metadata;
   ...........
}

然后来到doProcessConfigurationClass方法:

     

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
      throws IOException {
   ...........

   // Process any @PropertySource annotations
   for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
         sourceClass.getMetadata(), PropertySources.class,
         org.springframework.context.annotation.PropertySource.class)) {
      if (this.environment instanceof ConfigurableEnvironment) {
         processPropertySource(propertySource);
      }
   }

   // Process any @ComponentScan annotations
   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) {
         Set<BeanDefinitionHolder> scannedBeanDefinitions =
               this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
         for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
            if (ConfigurationClassUtils.checkConfigurationClassCandidate(
                  holder.getBeanDefinition(), this.metadataReaderFactory)) {
               parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
            }
         }
      }
   }
    (这后面的内容先不展开)
   // Process any @Import annotations
   processImports(configClass, sourceClass, getImports(sourceClass), true);

  ..............
   return null;
}

首先是获取@PropertySources、@PropertySource注解的内容,通过后面的

if (this.environment instanceof ConfigurableEnvironment) {
   processPropertySource(propertySource);
}

所以这里应该是将这两个注解的描叙设置到容器的环境中,先不展开了。

然后就是本次的关键,获取@ComponentScans、@ComponentScan注解的内容。如果不为空,这里又掉了一次this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(),ConfigurationPhase.REGISTER_BEAN),不过这次传的是REGISTER_BEAN,最开始是传的PARSE_CONFIGURATION。

获取关于@ComponentScans、@ComponentScan注解的属性描叙AnnotationAttributes后然后遍历调用:

this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
   ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
         componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
      ..............

   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));
   }

   scanner.setResourcePattern(componentScan.getString("resourcePattern"));

   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);
   }

   Set<String> basePackages = new LinkedHashSet<>();
   String[] basePackagesArray = componentScan.getStringArray("basePackages");
    ..........
   for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
      basePackages.add(ClassUtils.getPackageName(clazz));
   }
   if (basePackages.isEmpty()) {
      basePackages.add(ClassUtils.getPackageName(declaringClass));
   }

   scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
      @Override
      protected boolean matchClassName(String className) {
         return declaringClass.equals(className);
      }
   });
   return scanner.doScan(StringUtils.toStringArray(basePackages));
}

可以看到这里是将AnnotationAttributes描叙的内容设置到ClassPathBeanDefinitionScanner中:

                           

设置之后调用ClassPathBeanDefinitionScanner的doScan方法(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) {
      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 (candidate instanceof AbstractBeanDefinition) {
            postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
         }
         if (candidate instanceof AnnotatedBeanDefinition) {
            AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
         }
         if (checkCandidate(beanName, candidate)) {
            BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
            definitionHolder =
                  AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
            beanDefinitions.add(definitionHolder);
            registerBeanDefinition(definitionHolder, this.registry);
         }
      }
   }
   return beanDefinitions;
}

然后遍历basePackages包,再通过调用findCandidateComponents方法,去获取每个包下面定义的BeanDefinition:

        

String CLASSPATH_ALL_URL_PREFIX = "classpath*:";
private String resourcePattern = DEFAULT_RESOURCE_PATTERN;
static final String DEFAULT_RESOURCE_PATTERN = "**/*.class"

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
   Set<BeanDefinition> candidates = new LinkedHashSet<>();
   try {
      String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
            resolveBasePackage(basePackage) + '/' + this.resourcePattern;
      Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
      for (Resource resource : resources) {
         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);
                  }
            ..............
   return candidates;
}
private ResourcePatternResolver getResourcePatternResolver() {
   if (this.resourcePatternResolver == null) {
      this.resourcePatternResolver = new PathMatchingResourcePatternResolver();
   }
   return this.resourcePatternResolver;
}

获取搜索路径packageSearchPath下面的class文件:

                   

获取后遍历通过isCandidateComponent方法判断:

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;
}

可以看到这里就是处理在@ComponentScans、@ComponentScan中加的excludeFilters、includeFilters属性值实现TypeFilter接口的类。进行match,一种是排除、一种是包括,类似于前面讲的Condition注解的作用。

满足的话,然后就将扫描到的class转换到系统,描叙为ScannedGenericBeanDefinition Beandefinition。

               

将这些resource描叙为ScannedGenericBeanDefinition并添加到candidates后就返回到doScan(String... basePackages)方法的调用:

    

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);
     ........
}

这里就是设置ScannedGenericBeanDefinition beanDefinition的属性。类型上章讲的设置AnnotatedGenericBeanDefinition的属性。

这些都处理完了后,我们再回到doProcessConfigurationClass方法,下面就是最开始描叙的

processImports(configClass, sourceClass, getImports(sourceClass), true);

// Process any @ImportResource annotations
AnnotationAttributes importResource =
      AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
  ............

这里就先不展开了,这些流程等到梳理ApplicationContext容器的时候,再具体分析其内容。本次主要是是描叙ScannedGenericBeanDefinition的初始化过程。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值