Spring源码分析之组件扫描配置类(下)

bean定义解析完成后,验证是否有解析错误,创建配置类读取类


do {
  parser.parse(candidates);
  parser.validate();

  Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(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);
}
while (!candidates.isEmpty());

从配置类中加载bean定义


public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
  TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
  for (ConfigurationClass configClass : configurationModel) {
    loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
  }
}

判断是否跳过配置类

private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass,
    TrackedConditionEvaluator trackedConditionEvaluator) {

  if (trackedConditionEvaluator.shouldSkip(configClass)) {
    String beanName = configClass.getBeanName();
    if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
      this.registry.removeBeanDefinition(beanName);
    }
    this.importRegistry.removeImportingClassFor(configClass.getMetadata().getClassName());
    return;
  }

  if (configClass.isImported()) {
    registerBeanDefinitionForImportedConfigurationClass(configClass);
  }
  for (BeanMethod beanMethod : configClass.getBeanMethods()) {
    loadBeanDefinitionsForBeanMethod(beanMethod);
  }
  loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
  loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

注册导入配置类


private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
  AnnotationMetadata metadata = configClass.getMetadata();
  AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);

  ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
  configBeanDef.setScope(scopeMetadata.getScopeName());
  String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
  AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);

  BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
  definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
  this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
  configClass.setBeanName(configBeanName);

  if (logger.isDebugEnabled()) {
    logger.debug("Registered bean definition for imported class '" + configBeanName + "'");
  }
}

注册从bean方法得到的bean定义


private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
  ConfigurationClass configClass = beanMethod.getConfigurationClass();
  MethodMetadata metadata = beanMethod.getMetadata();
  String methodName = metadata.getMethodName();

  // 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
  AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
  List<String> names = new ArrayList<String>(Arrays.asList(bean.getStringArray("name")));
  String beanName = (names.size() > 0 ? 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)) {
    return;
  }

  ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
  beanDef.setResource(configClass.getResource());
  beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));

  if (metadata.isStatic()) {
    // static @Bean method
    beanDef.setBeanClassName(configClass.getMetadata().getClassName());
    beanDef.setFactoryMethodName(methodName);
  }
  else {
    // instance @Bean method
    beanDef.setFactoryBeanName(configClass.getBeanName());
    beanDef.setUniqueFactoryMethodName(methodName);
  }
  beanDef.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
  beanDef.setAttribute(RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);

  AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);

  Autowire autowire = bean.getEnum("autowire");
  if (autowire.isAutowire()) {
    beanDef.setAutowireMode(autowire.value());
  }

  String initMethodName = bean.getString("initMethod");
  if (StringUtils.hasText(initMethodName)) {
    beanDef.setInitMethodName(initMethodName);
  }

  String destroyMethodName = bean.getString("destroyMethod");
  if (destroyMethodName != null) {
    beanDef.setDestroyMethodName(destroyMethodName);
  }

  // Consider scoping
  ScopedProxyMode proxyMode = ScopedProxyMode.NO;
  AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
  if (attributes != null) {
    beanDef.setScope(attributes.getString("value"));
    proxyMode = attributes.getEnum("proxyMode");
    if (proxyMode == ScopedProxyMode.DEFAULT) {
      proxyMode = ScopedProxyMode.NO;
    }
  }

  // Replace the original bean definition with the target one, if necessary
  BeanDefinition beanDefToRegister = beanDef;
  if (proxyMode != ScopedProxyMode.NO) {
    BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
        new BeanDefinitionHolder(beanDef, beanName), this.registry, proxyMode == ScopedProxyMode.TARGET_CLASS);
    beanDefToRegister = new ConfigurationClassBeanDefinition(
        (RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata);
  }

  if (logger.isDebugEnabled()) {
    logger.debug(String.format("Registering bean definition for @Bean method %s.%s()",
        configClass.getMetadata().getClassName(), beanName));
  }

  this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}

从导入资源中加载bean定义


private void loadBeanDefinitionsFromImportedResources(
    Map<String, Class<? extends BeanDefinitionReader>> importedResources) {

  Map<Class<?>, BeanDefinitionReader> readerInstanceCache = new HashMap<Class<?>, BeanDefinitionReader>();

  for (Map.Entry<String, Class<? extends BeanDefinitionReader>> entry : importedResources.entrySet()) {
    String resource = entry.getKey();
    Class<? extends BeanDefinitionReader> readerClass = entry.getValue();

    // Default reader selection necessary?
    if (BeanDefinitionReader.class == readerClass) {
      if (StringUtils.endsWithIgnoreCase(resource, ".groovy")) {
        // When clearly asking for Groovy, that's what they'll get...
        readerClass = GroovyBeanDefinitionReader.class;
      }
      else {
        // Primarily ".xml" files but for any other extension as well
        readerClass = XmlBeanDefinitionReader.class;
      }
    }

    BeanDefinitionReader reader = readerInstanceCache.get(readerClass);
    if (reader == null) {
      try {
        // Instantiate the specified BeanDefinitionReader
        reader = readerClass.getConstructor(BeanDefinitionRegistry.class).newInstance(this.registry);
        // Delegate the current ResourceLoader to it if possible
        if (reader instanceof AbstractBeanDefinitionReader) {
          AbstractBeanDefinitionReader abdr = ((AbstractBeanDefinitionReader) reader);
          abdr.setResourceLoader(this.resourceLoader);
          abdr.setEnvironment(this.environment);
        }
        readerInstanceCache.put(readerClass, reader);
      }
      catch (Exception ex) {
        throw new IllegalStateException(
            "Could not instantiate BeanDefinitionReader class [" + readerClass.getName() + "]");
      }
    }

    // TODO SPR-6310: qualify relative path locations as done in AbstractContextLoader.modifyLocations
    reader.loadBeanDefinitions(resource);
  }
}

从导入的bean定义注册中心中加载bean定义

private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
  for (Map.Entry<ImportBeanDefinitionRegistrar, AnnotationMetadata> entry : registrars.entrySet()) {
    entry.getKey().registerBeanDefinitions(entry.getValue(), this.registry);
  }
}

判断解析后的bean定义数量是否和之前保持一致,如果不一致的话就需要在解析一遍新加的这些bean定义,有可能这些新增加的bean定义中也含有需要解析的bean定义信息


candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
  String[] newCandidateNames = registry.getBeanDefinitionNames();
  Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames));
  Set<String> alreadyParsedClasses = new HashSet<String>();
  for (ConfigurationClass configurationClass : alreadyParsed) {
    alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
  }
  for (String candidateName : newCandidateNames) {
    if (!oldCandidateNames.contains(candidateName)) {
      BeanDefinition beanDef = registry.getBeanDefinition(candidateName);
      if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory) &&
          !alreadyParsedClasses.contains(beanDef.getBeanClassName())) {
        candidates.add(new BeanDefinitionHolder(beanDef, candidateName));
      }
    }
  }
  candidateNames = newCandidateNames;
}

将ImportRegistry注册为bean以支持ImportAware @Configuration类,最后清除缓存


// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (singletonRegistry != null) {
  if (!singletonRegistry.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
    singletonRegistry.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
  }
}

if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
  ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}

bean工厂后处理方法需要处理前面方法postProcessBeanDefinitionRegistry没处理过的bean工厂的bean定义信息


public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
  int factoryId = System.identityHashCode(beanFactory);
  if (this.factoriesPostProcessed.contains(factoryId)) {
    throw new IllegalStateException(
        "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);
}

然后增加配置类,如果@Configuration类被代理,则始终代理目标类


public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
  Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<String, AbstractBeanDefinition>();
  for (String beanName : beanFactory.getBeanDefinitionNames()) {
    BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
    if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
      if (!(beanDef instanceof AbstractBeanDefinition)) {
        throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
            beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
      }
      else if (logger.isWarnEnabled() && beanFactory.containsSingleton(beanName)) {
        logger.warn("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;
  }
  ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
  for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
    AbstractBeanDefinition beanDef = entry.getValue();
    // If a @Configuration class gets proxied, always proxy the target class
    beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
    try {
      // Set enhanced subclass of the user-specified bean class
      Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
      Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
      if (configClass != enhancedClass) {
        if (logger.isDebugEnabled()) {
          logger.debug(String.format("Replacing bean definition '%s' existing class '%s' with " +
              "enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
        }
        beanDef.setBeanClass(enhancedClass);
      }
    }
    catch (Throwable ex) {
      throw new IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
    }
  }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值