Spring IOC源码--读取BeanDefintion

bg:25届毕业生,目前在实习,记录一下学习成长过程中的感悟。

个人心得:如果没有源码阅读经验的新手在刚接触源码的时候很容易晕头转向。网上关于Spring源码的资料和视频很多,但是都很杂,而且每个人的痛点都不一样,就需要从各个资料中去整合。这个过程。。。非常的痛苦。下面就具体说明一下我的学习方式和个人理解,理解有误的地方欢迎指正。


 Spring IOC流程
根据流程图可以看IOC容器创建Bean对象可以大致分为三步:
1. 读取BeanDefinition(Bean定义信息)
2. 实例化(创建Bean)
3. 初始化(填充Bean)

读取BeanDefinition


Spring两大容器BeanFactory和ApplicationContext我就不介绍了,这里详细介绍一下ApplicationContext的实现子类AnnotationConfigApplicationContext(注解)以及对比一下ClassPathXmlApplicationContext(XML)。

两个类的构造函数都调用了refresh()方法,该方法继承于AbstractApplicationContext,也是容器管理Bean的主要方法。Spring要想管理Bean,首先要先new一个BeanFactory容器,依托这个容器去管理。这两个类第一个不同的地方就在于容器创建时间,AnnotationConfigApplicationContext在调用this()无参构造的同时会调用父类GenericApplicationContext的无参构造new一个DefaultListableBeanFactory。而ClassPathXmlApplicationContext发生在refresh()中的obtainFreshBeanFactory()方法。在容器准备就绪后就可以开始读取Beandefinition了。


第二个不同也来了,AnnotationConfigApplicationContext使用scan()方法读取,而ClassPathXmlApplicationContext同样发生在obtainFreshBeanFactory()方法里的
loadBeanDefinitions()方法中。接下来具体讲一下scan()方法。

scan()方法通过一次次套娃的重写和调用,定位到一个重要方法doScan()。在该方法中有一个findCandidateComponents()方法会去读取候选的BeanDefinition,也就是加了@Components注解的Bean。该方法首先会通过读取Resource的方式将指定包下的class文件读取出来,再通过isCandidateComponent()方法判断是否添加了@Components注解,在isCandidateComponent()方法中可以看到一个includeFilters,而这个list里Components的值哪里来的呢?这就要回到AnnotationConfigApplicationContext的构造函数了,在构造函数里new了一个ClassPathBeanDefinitionScanner。顺着这个scanner的构造函数能找到registerDefaultFilters()方法,在这个方法里将Components注册到了includeFilters。

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


有了候选BeanDefinition之后,通过对这些BeanDefinition进行扩展处理、封装等操作,开始通过registerBeanDefinition()方法注册。同样的,通过一次次的套娃重写和调用,会来到DefaultListableBeanFactory的registerBeanDefinition(),该方法会把BeanDefinition注册到beanDefinitionMap中。至此读取BeanDefinition工作告一段落。
 

if (hasBeanCreationStarted()) {
    // Cannot modify startup-time collection elements anymore (for stable iteration)
    synchronized (this.beanDefinitionMap) {
        this.beanDefinitionMap.put(beanName, beanDefinition);
        List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
           updatedDefinitions.addAll(this.beanDefinitionNames);
           updatedDefinitions.add(beanName);
        this.beanDefinitionNames = updatedDefinitions;
        removeManualSingletonName(beanName);
    }
}
else {
    // Still in startup registration phase
    this.beanDefinitionMap.put(beanName, beanDefinition);
    this.beanDefinitionNames.add(beanName);
    removeManualSingletonName(beanName);
}
    this.frozenBeanDefinitionNames = null;}

剩下的后续慢慢写。。。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值