概述
想必@Component
注解大家一直在使用,只要类上加上它,就可以被Spring容器管理,那大家有想过它是怎么实现的吗?本篇文章就带领到家揭秘。
注解介绍
用来标记的类是一个“组件”或者说是一个Bean,Spring会自动扫描标记@Component
注解的类作为一个Spring Bean对象。
注解源码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
*/
String value() default "";
}
属性说明:
value
: 自定义当前组件或者说bean的名称,可以不配置, 不配置的话默认为组件的首字母小写的类名。
元注解说明:
- 该注解只能使用在类,接口、枚举、其他注解上
- 该注解的生命周期是运行时JVM
@Indexed
元注解在spring 5.0引入,用于项目编译打包时,会在自动生成META-INF/spring.components
文件,简历索引,从而提高组件扫描效率,减少应用启动时间。
注解使用
- 定义
Person
类,被@Component
注解修饰
- 检查
Person
类是否在扫描路径下
- 获取bean验证
小结: 通过添加@Component
能够将类转为Spring中的Bean对象,前提是能过够被扫描到。
原理解析
阅读源码,我们查看@Component
注解的源码,从中可以看到一个关键的类ClassPathBeanDefinitionScanner
,我们可以从这个类下手,找到切入点。
分析ClassPathBeanDefinitionScanner
类,找到核心方法doscan
, 打个断点,了解整个调用链路。
具体分析结果如下:
SpringBoot
应用启动会注册ConfigurationClassPostProcessor
这个Bean
,它实现了BeanDefinitionRegistryPostProcessor
接口,而这个接口是Spring
提供的一个扩展点,可以往BeanDefinition Registry
中添加BeanDefintion
。所以,只要能够扫描到@Component
注解的类,并且把它注册到BeanDefinition Registry
中即可。
- 关键方法
ConfigurationClassPostProcessor
的postProcessBeanDefinitionRegistry
,查找@Component
的类,并进行注册。
- 我们直接跳到是如何查找
@Component
的类的,核心方法就是ClassPathBeanDefinitionScanner#doScan
。
protected Set
- 重点关注
ClassPathBeanDefinitionScanner#findCandidateComponents
方法,找出候选的Bean Component
。
public Set
private Set
// 判断是否候选的Bean Component
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
// exclude过滤器,在exclude过滤其中的,会直接排除掉,返回false
for (TypeFilter tf : this.excludeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return false;
}
}
// include过滤器, 这里会看到有AnnotationTypeFilter,注解类型过滤器
for (TypeFilter tf : this.includeFilters) {
// 调用AnnotationTypeFilter的match方法,来判断是否满足条件
if (tf.match(metadataReader, getMetadataReaderFactory())) {
// 下面在进行Condition的判断,就是类上的@Conditional,这里不是重点
return isConditionMatch(metadataReader);
}
}
return false;
}
而这个AnnotationTypeFilter
默认是在构造函数中注册进去的。
小结:
@Component
到Spring bean
容器管理过程如下:
- 初始化时设置了
Component
类型过滤器; - 根据指定扫描包扫描
.class
文件,生成Resource
对象; - 解析
.class
文件并注解归类,生成MetadataReader
对象; - 使用第一步的注解过滤器过滤出有
@Component
类; - 生成
BeanDefinition
对象; - 把
BeanDefinition
注册到Spring
容器。
总结
经过这篇文章文章,是不是对@Component
的使用和实现原理一清二楚了呢,其实Spring
中还有@Service
、@Controller
和@Repository
等注解,他们和@Component
有什么区别呢,你知道吗?
-
容器
+关注
关注
0文章
495浏览量
22060 -
spring
+关注
关注
0文章
340浏览量
14338 -
注解
+关注
关注
0文章
18浏览量
2672
发布评论请先 登录
相关推荐
评论