Springboot扫描注解类

Springboot的启动过程中,核心在于AbstractApplicationContext的refresh方法,其中涉及到BeanDefinition的扫描和注册。ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry处理@Configuration类,通过processConfigBeanDefinitions解析所有组件。扫描组件时,若无basePackages配置,会基于声明的类名进行扫描。ClassPathBeanDefinitionScanner的doScan方法用于扫描指定包下的组件,然后注册BeanDefinition,初始化并未立即执行,而是在后续bean创建时进行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Springboot扫描注解类的入口在AbstractApplicationContext的refresh中,对启动步骤不太了解的,可参考springboot启动过程源码_spring-boot-starter源码-优快云博客

BeanDefinitionRegistryPostProcessor接口有多个实现类,扫描Controller、Service等组件,这里使用的是ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry。

查看processConfigBeanDefinitions方法中的parser.parse(candidates),作用为解析所有@Configuration类,所有组件注解都包含@Configuration,实际就是解析

所有组件。

下图,如果BeanDefinition属于AnnotatedBeanDefinition,就开始解析注解bean定义。

在处理配置类的注解时,会找到ComponentScans注解,并解析其内容(@SpringBootApplication注解就包含@ComponentScan),由于未配置basePackages属性,解析到最后使用声明的类名。

后面扫描包,通过查看doScan方法的实现类,可以看到有两个,一个是ClassPathBeanDefinitionScanner(spring),另一个是ClassPathMapperScanner(使用mybatis集成的)。

这里使用的是ClassPathBeanDefinitionScanner的doscan方法。

扫描basePackage下的组件。

再对beanDefinition做一些后置处理。

上面完成了初步的BeanDefinition构建,在checkCandidate方法中将决定是否注册该BeanDefinition。

调用registerBeanDefinition方法开始注册BeanDefinition。

在DefaultListableBeanFactory的registerBeanDefinition方法中进行注册。

判断是否开始了bean创建。

已经有2个框架类开始创建,进入synchronized方法块进行添加。

注册完bean definition后同时给bean name注册别名。

关于BeanDefinition中的class是如何加装的,请查看ConfigurationClassPostProcessor类的processConfigBeanDefinitions方法。

ConfigurationClassBeanDefinitionReader的loadBeanDefinitionsForConfigurationClass

经过多个方法调用后,使用 ClassUtils.forName(className, classLoader)加载class

这里Class.forName的initialize设置为false,只是与class文件进行了关联,还未初始化,初始化在后面。

### 组件扫描与自定义注解 为了使Spring Boot应用程序能够扫描并识别特定或自定义注解,通常的做法是在创建这些注解之后,在配置类中通过`@ComponentScan`指定基础路径,并设置过滤条件来含所需的注解。当使用默认的组件扫描机制时,Spring会查找带有标准注解(如`@Component`及其变体)的类;对于非标准注解,则需额外指明。 例如,如果有一个名为`MyCustomAnnotation`的自定义注解希望被纳入组件管理: ```java // 定义自定义注解 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface MyCustomAnnotation { } ``` 接着可以在启动类或者其他配置类里调整组件扫描策略如下所示[^1]: ```java @Configuration @ComponentScan(basePackages = "com.example", includeFilters = {@Filter(type = FilterType.ANNOTATION, classes = MyCustomAnnotation.class)}, useDefaultFilters = false) public class AppConfig { } ``` 这里的关键在于设置了`includeFilters`参数,它允许开发者基于不同的准则筛选目标bean候选者。上述例子仅限定了具有`MyCustomAnnotation`标记的服务会被考虑进入容器内。同时关闭了默认滤镜(`useDefaultFilters=false`)意味着除非特别指出,其他任何形式的标准组件都不会自动加入到上下文中[^2]。 另外一种方法是直接在主程序入口处添加相应的属性配置,比如通过命令行参数或者application.properties/yml文件的形式传递给`spring-boot-starter-parent`项目下的依赖项,从而实现全局性的控制效果[^4]: ```properties # application.properties spring.main.sources=com/example/package-with-custom-annotations ``` 这样做可以让整个工程更加灵活地适应不同环境下的需求变化,而无需频繁修改源码本身。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kenick

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值