Springboot - 包扫描原理解析_有机后浪的博客-CSDN博客_spring扫描包原理

Spring中的包扫描

在Spring中bean的注入有两种方式:

  • 自定义bean:xml或配置类
  • 注解,设置自动扫描

Spring中xml配置文件:
在这里插入图片描述

**配置类:**在类上加注解@Configuration,将类设置为配置类代替xml配置文件
在这里插入图片描述

由程序员手动设置bean是比较繁琐的,Spring又提供了偷懒的方法

注解、自动扫描:

springmvc.xml中<context:component-scan base-package="com.learn.controller"/>,即可扫描controller包下的所有bean

在这里插入图片描述

@Controller注解即表示该类为Spring中的一个bean

在这里插入图片描述

配置类中的自动扫描:即然@Configuration注解的配置类类似与xml配置文件,那能不能设置自动扫描?

@ComponentScan 注解:默认扫描该类所在的包下所有的配置类

在这里插入图片描述

那么没有在Config类中注入的bean,只要在当前目录下设置了,就可以从Spring容器中得到:

例如:当前目录下Beer并没有在Config中注入

在这里插入图片描述

Beer类设置为Spring组件:
在这里插入图片描述

测试类依旧可以直接得到:

在这里插入图片描述

Spring中通过@ComponentScan注解或者 < context:component-scan >标签完成包扫描

那么SpringBoot中呢?


SpringBoot中的包扫描

我们知道SpringBoot中:我们编写的类比较放置在xxApplication类所在目录下

这不就是前面Spring中的包扫描:扫描该类所在的包下所有的配置类

一个SpringBoot案例:

在这里插入图片描述

在这里插入图片描述

我们找不到任何关于包扫描的xml或者注解,定义好一个controller,然后启动就可以访问了?这是为什么?

这就是为什么说SpringBoot是Spring的精简加强版


SpringBoot包扫描原理

一切的秘密都在这:

在这里插入图片描述

SpringBoot的启动类中有很多东西,这里仅分析包扫描的原理

@SpringBootApplication

@SpringBootApplication注解的三个重要子注解:

在这里插入图片描述

  • @SpringBootConfiguration注解就是SpringBoot版的@Configuration注解:表示这是一个配置类
  • @EnableAutoConfiguration注解是设置启动时的自动装配
  • @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })即包扫描

里面的内容是什么意思呢?excludeFilters表示哪些类不用被扫描到

在这里插入图片描述

  • @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class)

custom表示自定义过滤规则(需要实现TypeFilter接口),TypeExcludeFilter就是SpringBoot定义的过滤类

  • @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)

自定义的匹配注册的自动配置类的过滤类AutoConfigurationExcludeFilter

那么是如何实现扫描该类所在的包呢?

SpringApplication.run(MyspringbootApplication.class, args)

该方法是SpringBoot的核心,其中有很多方法用于准备SpringBoot的环境、配置等

我们关注3个有关context方法:

  • createApplicationContext()

  • prepareContext(…)

  • refreshContext(context)

createApplicationContext: 创建Spring容器,返回ConfigurableApplicationContext
我们都知道ApplicationContext就是Spring的核心的IoC容器

在这里插入图片描述

prepareContext: 即准备context

其中有一个load(context, sources.toArray(new Object[0]))方法(多层方法),最终进入

在这里插入图片描述

在这里插入图片描述

isComponent方法判断类是否有Component的注解,明显启动类是有的,即将启动类注册

refreshContext(context):刷新context

很复杂
refreshContext方法 -》 invokeBeanFactoryPostProcessors方法 -》ConfigurationClassPostProcessor类 -》 processConfigBeanDefinitions方法 -》 parser.parse(candidates)方法 -》parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());方法 -》 processConfigurationClass方法 -》doProcessConfigurationClass方法

终于到了处理ComponentScan注解的方法:

在这里插入图片描述

其中的componentScans.isEmpty()的判断,即判定配置@ComponentScan的这个属性,得到添加的这个启动类的名字的最后一个点之前的路径,比如启动类是A.B.C.D.class, 那么路径就是A.B.C.D

Spring会通过传入的路径来遍历下面的每一个class


结语

SpringBoot是Spring的简化,需要配置的操作全部实现了自动化(自动装配)

SpringBoot的包扫描是隐藏的,需要深究才能找到

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐