spring源码---IOC:注册bean(注解方式)

接着上一节,我们已经把配置类中的所有信息都解析出来,放到了configClass中,现在我们调用loadBeanDefinition()方法,注解解析出来的bean。

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) { //创建配置类 bean 定义 读取器
   this.reader = new ConfigurationClassBeanDefinitionReader(
         registry, this.sourceExtractor, this.resourceLoader, this.environment,
         this.importBeanNameGenerator, parser.getImportRegistry());
}
this.reader.loadBeanDefinitions(configClasses);//【加载】bean定义
alreadyParsed.addAll(configClasses); //添加到已解析的集合中

调用reader,注解方式使用的是ConfigurationClassBeanDefinitionReader类,而xml方式使用的是DefaultBeanDefinitionReader。

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

遍历一个一个处理configClass,我们实验demo中只配置了一个配置类,所以这里只有一个configClass

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.removeImportingClass(configClass.getMetadata().getClassName());
      return;
   }

   if (configClass.isImported()) { //是否是@import进来的
      registerBeanDefinitionForImportedConfigurationClass(configClass);
   }
   for (BeanMethod beanMethod : configClass.getBeanMethods()) { //处理@Bean注解方法
      loadBeanDefinitionsForBeanMethod(beanMethod); //一个一个方法处理
   }
    //处理@importResource资源
   loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
    //处理 ImportBeanDefinitionRegister接口的实现类,比如aop中的
   loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

找到了处理configClass的地方,这里分为了4个处理方式,分别对应了@import,@Bean,@ImportResources,ImportBeanDefinitionRegister接口的实现类,第二中是很普通的,而第四种用在了aop的开启注解中使用,接下来我们直接看最常用的:

1.Bean

private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
   ConfigurationClass configClass = beanMethod.getConfigurationClass();
   MethodMetadata metadata = beanMethod.getMetadata();
   String methodName = metadata.getMethodName();
    //是否跳过
   if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
      configClass.skippedBeanMethods.add(methodName);
      return;
   }
   if (configClass.skippedBeanMethods.contains(methodName)) {
      return;
   }
   //找到@Bean注解的属性信息 具有5个属性
   AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
    //名字处理
   List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
   String beanName = (!names.isEmpty() ? names.remove(0) : methodName);

   for (String alias : names) {
      this.registry.registerAlias(beanName, alias);
   }
   //beanDefinition 封装
   ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
   beanDef.setResource(configClass.getResource());
   beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
    //各种注解处理:Autowire,initMethod,。。也就是@Bean自带五个属性,进行处理
   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(AbstractBeanDefinition.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");
   beanDef.setDestroyMethodName(destroyMethodName);
....
    //注册到BeanFactory中,作为BeanDefinition保存在集合中
   this.registry.registerBeanDefinition(beanName, beanDefToRegister); //注册
}

解析完毕之后,就注册到DefaultBeanFactory中,等待被实例化,实例化是在refresh()方法的第十一步中,实例化单例非懒加载的bean。

2.@ImposrResource

资源处理,使用资源读取器,

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

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

   importedResources.forEach((resource, readerClass) -> {
      // 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);
         }
      }
      reader.loadBeanDefinitions(resource); //使用xml的加载方式进行解析
   });
}

3.加载接口实现类

    处理方式比较简单,直接把该接口的唯一方法,执行就可以了。

private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
   registrars.forEach((registrar, metadata) ->
         registrar.registerBeanDefinitions(metadata, this.registry)); //调用方法实现
}

回到ConfigurationClassPostProcessor类中,加载完毕之后,保存configClasses,然后在beanFactory中,找出新加入的beanDefinition再一次进行解析,递归解析:

    candidates.clear(); //处理完,一次清空
   //现在的bean 大于了最开始的bean数量,进入
   if (registry.getBeanDefinitionCount() > candidateNames.length) {
      String[] newCandidateNames = registry.getBeanDefinitionNames(); //获得新的beanNames 集合
      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)) { //新的Bean
            BeanDefinition bd = registry.getBeanDefinition(candidateName);
            if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                  !alreadyParsedClasses.contains(bd.getBeanClassName())) {
               candidates.add(new BeanDefinitionHolder(bd, candidateName)); //封城成为xxholder保存,这样就存在一种循环遍历
            }
         }
      }
      candidateNames = newCandidateNames;
   }
}
while (!candidates.isEmpty());

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值