概述
想必@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文章
531瀏覽量
22965 -
spring
+關注
關注
0文章
341瀏覽量
15935 -
注解
+關注
關注
0文章
18瀏覽量
2849
發布評論請先 登錄
相關推薦
熱點推薦
Spring Boot如何實現異步任務
Spring Boot 提供了多種方式來實現異步任務,這里介紹三種主要實現方式。 1、基于注解 @Async @Async 注解是
使用Spring自定義注解的實現
執行器。其本質就是通過外部參數進行一次路由和Spring mvc做的事情類似。簡單看了Spring mvc的實現原理之后,決定使用自定義注解的方式來
發表于 09-28 11:55
?0次下載
Spring應用 1 springXML配置說明
開發過程。會使用注解形式的開發模式。但使用相應的注解需要spring.xml中定義相應的BeanProcessor,這樣顯得很笨重。 使用@Autowired
發表于 01-13 12:20
?541次閱讀
spring中聲明式事務實現原理猜想
? @Transactional注解簡介 @Transactional 是spring中聲明式事務管理的注解配置方式,相信這個注解的作用大家
淺談Spring事務底層原理
開啟Spring事務本質上就是增加了一個Advisor,但我們使用@EnableTransactionManagement注解來開啟Spring事務是,該注解代理的功能就是向
Spring Web MVC注解
RequestMapping注解的主要用途是將Web請求與請求處理類中的方法進行映射。Spring MVC和Spring WebFlux都通過`RquestMappingHandler
Spring Bean相關的4個注解及使用方法
ComponentScan`注解用于配置Spring需要掃描的被組件注解注釋的類所在的包。可以通過配置其basePackages屬性或者value屬性來配置需要掃描的包路徑。value屬性是basePackages的別名。此
Spring Dependency Inject與Bean Scops注解
DependsOn`注解可以配置Spring IoC容器在初始化一個Bean之前,先初始化其他的Bean對象。下面是此注解使用示例代碼:
Spring Kafka的各種用法
Kafka 是不支持消息重試的。但是 Spring Kafka 2.7+ 封裝了 Retry Topic 這個功能。 1. @RetryableTopic 使用注解的方式啟用 Retry Topic,在
Spring 的線程池應用
我們在日常開發中,經常跟多線程打交道,Spring 為我們提供了一個線程池方便我們開發,它就是 ThreadPoolTaskExecutor ,接下來我們就來聊聊 Spring 的線程池吧
springboot核心注解
Spring Boot 是基于 Spring 框架的開源框架,它可以幫助開發者快速構建、部署和運行獨立的、生產級的 Spring 應用程序。Spring Boot 提供了一系列核心
SpringBoot核心注解由幾個注解組成
Spring Boot 是一個開源的 JavaEE 開發框架,它以簡化 Spring 框架的配置與開發為目標,旨在讓開發者能快速構建獨立、生產級別的應用程序。Spring Boot 提供了大量用于
Spring中@Component注解是怎么實現的
評論