Spring IOC - Bean的扫描

这篇具有很好参考价值的文章主要介绍了Spring IOC - Bean的扫描。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        @Component及其衍生注解:@Configuration、@Controller、@Service、@Repository标记的类,被Spring IOC扫描到后,即可被容器管理起来。其原理基本涵盖在AnnotationConfigApplicationContext构造函数体的三行代码里。

public AnnotationConfigApplicationContext(String... basePackages) {
   this();
   scan(basePackages);
   refresh();
}

1. this()

        这个无参构造方法做了三件事情:

  • 首先创建bean工厂,实际上是在父类GenericApplicationContext的构造器里完成的
public GenericApplicationContext() {
   this.beanFactory = new DefaultListableBeanFactory();
}
  • 然后初始化reader和scanner,这两个类就是AnnotationConfigApplicationContext类中的成员变量,作用是相同的,都是用来注册BeanDefinition对象,只不过场景不同
public AnnotationConfigApplicationContext() {
// 生成并注册5个BeanDefinition
// 1.ConfigurationClassPostProcessor
// 2.AutowiredAnnotationBeanPostProcessor
// 3.CommonAnnotationBeanPostProcessor
// 4.EventListenerMethodProcessor
// 5.DefaultEventListenerFactory
   this.reader = new AnnotatedBeanDefinitionReader(this);
// spring提供api用来动态扫描注解
// 一般供扩展spring的时候用,内部扫描也是通过它
   this.scanner = new ClassPathBeanDefinitionScanner(this);
}

        AnnotatedBeanDefinitionReader用于解析单个类或一组类的注解,并将其转换为相应的BeanDefinition对象。它通常用于编程式地注册bean定义,即在代码中显式地调用AnnotatedBeanDefinitionReader的方法来注册bean定义。

        ClassPathBeanDefinitionScanner则用于在类路径下扫描指定的包,查找带有特定注解的类,并将其转换为相应的BeanDefinition对象。它通常用于自动化地注册bean定义,即在Spring容器启动时自动扫描指定包下的类,并将其转换为bean定义。

        总的来说,AnnotatedBeanDefinitionReader适用于手动注册bean定义,上述5个Spring提供的类就是通过reader编程试注入的,而ClassPathBeanDefinitionScanner适用于自动化注册bean定义。

        继续查看AnnotatedBeanDefinitionReader构造方法,上述5个类即通过AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)注册到beanDefinitionMap中

beanName

类名

是否BeanDefinitionRegistryPostProcessor

是否BeanFactoryPostProcessor

是否BeanPostProcessor

org.springframework.context.annotation.internalConfigurationAnnotationProcessor

ConfigurationClassPostProcessor

org.springframework.context.annotation.internalAutowiredAnnotationProcessor

AutowiredAnnotationBeanPostProcessor

org.springframework.context.annotation.internalCommonAnnotationProcessor

CommonAnnotationBeanPostProcessor

org.springframework.context.event.internalEventListenerProcessor

EventListenerMethodProcessor

org.springframework.context.event.internalEventListenerFactory

DefaultEventListenerFactory

2. scan(basePackages)

        在指定的基础包中执行扫描以查找组件类,这里是将扫描的类注册到beanDefinitionMap中。使用的正是上述创建scanner,该在创建的过程中,设置了一个@Component的注解类型过滤器,正是这个过滤器将扫描到的所有类过滤出标记了@Component及其衍生注解的类,逻辑如下:

Spring IOC - Bean的扫描,spring,java,后端

//判断元信息读取器读取的类是否符合容器定义的注解过滤规则
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
   // 如果读取的类的注解在排除注解过滤规则中,返回false
   for (TypeFilter tf : this.excludeFilters) {
      // 规则匹配功能
      if (tf.match(metadataReader, getMetadataReaderFactory())) {
         return false;
      }
   }
   // 如果读取的类的注解在包含的注解的过滤规则中,则返回true
   // 这里的includeFilters已经有了@Component过滤器
   for (TypeFilter tf : this.includeFilters) {
      if (tf.match(metadataReader, getMetadataReaderFactory())) {
         return isConditionMatch(metadataReader);
      }
   }
   // 如果读取的类的注解既不在排除规则,也不在包含规则中,则返回false
   return false;
}

3. refresh()

    该方法是Spring应用上下文的核心方法,它负责完成Spring容器的初始化和刷新工作,由于篇幅有限,这里主要讲解与扫描和解析相关的方法:invokeBeanFactoryPostProcessors(beanFactory)

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   // getBeanFactoryPostProcessors()得到的是程序员通过API直接添加的BeanFactory
   // 这里getBeanFactoryPostProcessors()90%情况都是返回空
   // 只有10%情况不为空【程序员通过API手动添加】
   PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

   // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
   // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
   if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }
}

         接下来是invokeBeanFactoryPostProcessors方法了,该方法会调用在上述注入到beanDefinitionMap中的Spring内置的类BeanDefinitionRegistryPostProcessor及BeanFactoryPostProcessor对应的接口方法。整体逻辑可以分成两部分看:

  • 先调用BeanDefinitionRegistryPostProcessor的子类;
  • 再调用BeanFactoryPostProcessor的子类。

Spring IOC - Bean的扫描,spring,java,后端

        这里面会调用一个关键类ConfigurationClassPostProcessor,他会解析@Configuration标记的类,及类中@Bean方法,涉及到full和lite模式,由于篇幅有限,将在下一篇讲解。文章来源地址https://www.toymoban.com/news/detail-561288.html

到了这里,关于Spring IOC - Bean的扫描的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring6学习技术|IoC+基于xml管理bean

    尚硅谷Spring零基础入门到进阶,一套搞定spring6全套视频教程(源码级讲解) 控制反转。是一种设计思想。 通过id,通过class,和双重方式。 普通属性:String, Interger (set和构造器:感觉还是set比较方便) 特殊属性:null,特殊的大于小于等(xml转义字符,cdata) 对象:外部

    2024年02月21日
    浏览(37)
  • 【Spring篇】IOC/DI配置管理第三方bean

    🍓系列专栏:Spring系列专栏 🍉个人主页:个人主页 目录 一、案例:数据源对象管理 1.环境准备 2.实现Druid管理 3.实现C3P0管理 二、加载properties文件 1.第三方bean属性优化 2.读取单个属性 3.注意事项   三、核心容器 1.环境准备 2.容器   1.容器的创建方式 2.Bean的三种获取方式 3.容器

    2024年02月02日
    浏览(39)
  • 【Spring专题】Spring之Bean的生命周期源码解析——阶段二(二)(IOC之属性填充/依赖注入)

    由于Spring源码分析是一个前后联系比较强的过程,而且这边分析,也是按照代码顺序讲解的,所以不了解前置知识的情况下,大概率没办法看懂当前的内容。所以,特别推荐看看我前面的文章(自上而下次序): Spring底层核心原理解析【学习难度: ★★☆☆☆ 】 手写简易

    2024年02月12日
    浏览(30)
  • 【Spring类路径Bean定义信息扫描】

    补充一下: AbstractBeanDefinition、AnnotatedBeanDefinition都是spring框架中定义和处理BeanDefinition的类,他们在SpringIOC容器的核心机制中有重要的地位。 1. AbstractBeanDefinition: 是个抽象类,实现了 BeanDefinition 接口,为BeanDefinition提供了一些通用的方法和属性。 提供了BeanDefinition的基本结构

    2024年01月16日
    浏览(33)
  • 【仿写spring之ioc篇】四、实现bean的初始化阶段

    在Bean的初始化阶段有前置和后置方法,这个方法是通过BeanPostProcessor来管理的,下面我们对原有的项目结构做小小的更改。 对启动类作出修改,先检查有没有BeanPostProcessor的实现类,有的话就使用,没有就使用默认的。 第二次循环先检查是不是postProcessor,是的话就跳过就行

    2024年02月10日
    浏览(33)
  • 【Spring教程11】Spring框架实战:IOC/DI注解开发管理第三方bean的全面深入详解

    欢迎大家回到《 Java教程之Spring30天快速入门》,本教程所有示例均基于Maven实现,如果您对Maven还很陌生,请移步本人的博文《 如何在windows11下安装Maven并配置以及 IDEA配置Maven环境》,本文的上一篇为《 纯注解开发模式下的依赖注入和读取properties配置文件》 前面定义bean的时

    2024年02月04日
    浏览(42)
  • 4.是人就能学会的Spring源码教程-IOC容器创建Bean对象

    我们要关注一个接口 BeanFactory ,它是Spring IOC容器的根接口,也是容器的入口。 类的描述中已经清楚的说明了: 我们来看一下这个接口里面的方法。 我们可以看到有各种各样的 getBean 方法,让我们可以从容器中获取到各种各样的Bean对象。 BeanFactory 有一个实现类 DefaultListab

    2024年02月05日
    浏览(29)
  • 【Spring专题】Spring之Bean的生命周期源码解析——上(扫描生成BeanDefinition)

    由于Spring源码分析是一个前后联系比较强的过程,而且这边分析,也是按照代码顺序讲解的,所以不了解前置知识的情况下,大概率没办法看懂当前的内容。所以,特别推荐看看我前面的文章(自上而下次序): Spring底层核心原理解析——引导篇【学习难度: ★★☆☆☆ 】

    2024年02月13日
    浏览(30)
  • 【Spring专题】Spring之Bean的生命周期源码解析——阶段一(扫描生成BeanDefinition)

    由于Spring源码分析是一个前后联系比较强的过程,而且这边分析,也是按照代码顺序讲解的,所以不了解前置知识的情况下,大概率没办法看懂当前的内容。所以,特别推荐看看我前面的文章(自上而下次序): Spring底层核心原理解析——引导篇【学习难度: ★★☆☆☆ 】

    2024年02月13日
    浏览(31)
  • 11Spring IoC注解式开发(上)(元注解/声明Bean的注解/注解的使用/负责实例化Bean的注解)

    注解的存在主要是为了简化XML的配置。Spring6倡导全注解开发。 注解开发的优点 :提高开发效率 注解开发的缺点 :在一定程度上违背了OCP原则,使用注解的开发的前提是需求比较固定,变动较小。 自定义一个注解: 该注解上面修饰的注解包括:Target注解和Retention注解,这两个注

    2024年01月21日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包