Spring中的@ComponentScan注解詳解
Spring注解 @ComponentScan
1.添加 @ComponentScan 注解
創(chuàng)建一個(gè)配置類,在配置類上添加 @ComponentScan 注解。該注解默認(rèn)會(huì)掃描該類所在的包下所有的配置類,相當(dāng)于之前的
<context:component-scan>
2.獲取已經(jīng)注冊(cè)到容器中的 bean 的名稱以及數(shù)量
使用 ApplicationContext 的 getBeanDefinitionNames() 方法和getBeanDefinitionCount()獲取已經(jīng)注冊(cè)到容器中的 bean 的名稱以及數(shù)量
@SpringBootApplication
public class ZzyNotesApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(ZzyNotesApplication.class, args);
String[] beanDefinitionNames = context.getBeanDefinitionNames();
for (String beanName : beanDefinitionNames) {
System.out.println("beanName: " + beanName);
}
System.out.println("bean總數(shù):"+context.getBeanDefinitionCount());
}
}
3.@ComponentScan
@SpringBootApplication注解中已經(jīng)存在,也可以根據(jù)需要自定義 @SpringBootApplication(scanBasePackages = "")
常用參數(shù):
1.value || basePackages = "包路徑,默認(rèn)當(dāng)前類所在包"
2.excludeFilters 使用 excludeFilters 來(lái)按照規(guī)則排除某些包的掃描。
3.includeFilters 用includeFilters配置 掃描的類
優(yōu)先級(jí)由上之下,比如自定義的MyTypeFilter如果已經(jīng)Bean已經(jīng)在ioc容器中,或者上面的excludeFilters已經(jīng)過(guò)濾掉這個(gè)Bean,則不掃描這個(gè)類
- 參數(shù):
- FilterType.ANNOTATION :注解名規(guī)則,Service.class
- FilterType.ASSIGNABLE_TYPE : 按照給定的類型,比如當(dāng)前類型的父子類。
- FilterType.ASPECTJ :使用aspectj表達(dá)式
- FilterType.REGEX :使用正則指定
- FilterType.CUSTOM
4.useDefaultFilters
默認(rèn)為true ,會(huì)優(yōu)先執(zhí)行默認(rèn)的過(guò)濾器 對(duì) @Component、@ManagedBean、@Named注解的Bean進(jìn)行掃描 所以要改為false
配置類代碼如下
@Configuration
@ComponentScans(
{
@ComponentScan(value = "com.zzy.zzyNotes" ,useDefaultFilters = false),
@ComponentScan(value = "com.zzy.zzyNotes.spring.createBean",
excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Service.class}),//排除包含注解Service的類(不生效,原因未知)
@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {ExcludeMyAnnotation.class})//排除包含注解MyAnnotation2的類
},
includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {IncludeMyAnnotation.class}),//指定掃描包換注解MyAnnotation的類
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),//指定注解掃描包換注解Controller的類
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE , classes = {Person2.class}),//指定類型Person2的類
@ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})//自定義過(guò)濾規(guī)則
}
, useDefaultFilters = false//這個(gè)沒有效果,必須在啟動(dòng)類上的@ComponentScan( useDefaultFilters = false)中配置 false
)
}
)
public class BeanConfig {
}/**
* @author zzy
* @createDate: 2021-12-30 16:26:50
* @description: 自定義注解 指定某個(gè)類被掃描
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IncludeMyAnnotation {
}
/**
* @author zzy
* @createDate: 2021-12-30 16:26:50
* @description: 自定義注解 排除某個(gè)類被掃描
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExcludeMyAnnotation {
}
/**
* 掃描包自定義規(guī)則
* metadataReader:讀取到當(dāng)前正在掃描類的信息
* metadataReaderFactory:可以獲取到其他任何類的信息
* 注意:只有不滿足其它的規(guī)則,才會(huì)被自定義過(guò)濾規(guī)則判斷
* @author zzy
*/
public class MyTypeFilter implements TypeFilter {
/**
* @description: 掃描規(guī)則
* @params:
* @return: 返回true 加入IOC容器 false ,排除
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
//獲取當(dāng)前類注解信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//獲取當(dāng)前正在掃描類的信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//獲取當(dāng)前類資源信息 (比如類存在哪個(gè)盤,類的路徑 )
Resource resource = metadataReader.getResource();
String name = classMetadata.getClassName();
System.out.println("Filter掃描的類名:" + name);
if(name.contains("Person3")){
return true;
}
return false;
}
}
/**
* @author zzy
* @createDate: 2021-12-30 10:08:35
* @description: 創(chuàng)建Bean Person1 加IncludeMyAnnotation
*/
@IncludeMyAnnotation
public class Person1 {
}
/**
* @author zzy
* @createDate: 2021-12-30 10:10:37
* @description: 創(chuàng)建Bean Person1 加@ExcludeMyAnnotation 被排除
* 正常有@Component就會(huì)被掃描,加了@ExcludeMyAnnotation就會(huì)被排除
*/
@ExcludeMyAnnotation
@Component
public class Person2 {
}
/**
* @author zzy
* @createDate: 2021-12-30 17:03:44
* @description: 創(chuàng)建Bean Person3 符合MyTypeFilter過(guò)濾規(guī)則
*/
public class Person3 {
}
其他問題
優(yōu)先級(jí)
- 自定義的@ComponentScan優(yōu)先級(jí)大于@SpringBootApplication默認(rèn)的,要注意的是,
- 自定義的@ComponentScan的路徑一定要包含啟動(dòng)類項(xiàng)目路徑,默認(rèn)為配置類所在的路徑
注意
1.自定義@ComponentScan時(shí)注意控制的路徑范圍
2.有重名的Bean會(huì)注冊(cè)失敗
問題
spring 有默認(rèn)的規(guī)律規(guī)則 會(huì)對(duì) @Component、@ManagedBean、@Named注解的Bean進(jìn)行掃描,如果設(shè)置了
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Service.class})
但是加了@service的類依然被注冊(cè)到ioc
所以要設(shè)置 useDefaultFilters = false
到此這篇關(guān)于Spring中的@ComponentScan注解詳解的文章就介紹到這了,更多相關(guān)@ComponentScan注解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot中非容器類如何獲取配置文件數(shù)據(jù)
這篇文章主要介紹了springboot中非容器類如何獲取配置文件數(shù)據(jù)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
Java中的RASP機(jī)制實(shí)現(xiàn)詳解
這篇文章主要介紹了Java中的RASP實(shí)現(xiàn)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08
Java8 Stream對(duì)兩個(gè) List 遍歷匹配數(shù)據(jù)的優(yōu)化處理操作
這篇文章主要介紹了Java8 Stream對(duì)兩個(gè) List 遍歷匹配數(shù)據(jù)的優(yōu)化處理操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08
SpringBoot 中 CommandLineRunner的作用示例詳解
SpringBoot提供的一種簡(jiǎn)單的實(shí)現(xiàn)方案就是添加一個(gè)model并實(shí)現(xiàn)CommandLineRunner接口,實(shí)現(xiàn)功能的代碼放在實(shí)現(xiàn)的run方法中,本文給大家介紹SpringBoot中CommandLineRunner的作用,感興趣的朋友一起看看吧2025-06-06

