@ComponentScan
用於指定包的掃描路徑。用於代替spring的xml配置檔案中的<context:componet-scan base-package=""/>
標籤。
context:componet-scan
標籤
context:componet-scan
的作用
spring就會去自動掃描base-package對應的路徑或者該路徑的子包下面的帶有@Service
,@Component
,@Repository
,@Controller
註解的java檔案。
context:componet-scan
屬性
-
base-package
: 指定掃描路徑。 -
use-default-filters
: 是否使用預設的掃描過濾器。
-
use-default-filters=true
表示掃描包路徑的@Service
,@Component
,@Repository
,@Controller
註解的類;如果你不想全部掃描這些類,可以進行過濾,比如說你不想掃描@Controller
註解的類。
<context:componet-scan base-package="com.sff.app" use-default-filters="true">
<!--不掃描@Controller註解的類-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:componet-scan>
<context:componet-scan base-package="com.sff.app" use-default-filters="false">
<!--只掃描@Controller註解的類-->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:componet-scan>
-
use-default-filters=true
表示按照自定義規則掃描包路徑下的類;
@ComponentScan的使用
該註解是使用在我們的配置類上的。
/**
* 配置類等價於spring的配置檔案
*/
@Configuration
@ComponentScan(value = "com.sff.app",
includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class)},
useDefaultFilters = false)
public class AppConfig {
/*給容器中註冊一個bean,型別是方法返回值,id就是方法名稱*/
@Bean
public Person person() {
return new Person("Kate", 12);
}
}
@ComponentScan的屬性說明
@ComponentScan(value = "com.sff.app",useDefaultFilters = false,
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,
classes = {Controller.class, Service.class})})
@ComponentScan(value = "com.sff.app",
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,
classes = {Controller.class, Service.class})})
- useDefaultFilters: 是否使用預設的掃描過濾器,相當於
use-default-filters
的功能。 - excludeFilters: 指定掃描時需要按照什麼規則排除不掃描的類。
- includeFilters: 指定掃描時需要按照什麼規則掃描的類。
我們看下註解原始碼是怎麼定義的?
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
/*定義了包掃描路徑屬性*/
@AliasFor("basePackages")
String[] value() default {};
@AliasFor("value")
String[] basePackages() default {};
/*預設使用預設的過濾,全部掃描*/
boolean useDefaultFilters() default true;
/*過濾器屬性,過濾器是一個陣列,可以配置多個*/
ComponentScan.Filter[] includeFilters() default {};
ComponentScan.Filter[] excludeFilters() default {};
/*過濾器註解*/
@Retention(RetentionPolicy.RUNTIME)
@Target({})
public @interface Filter {
/*預設的過濾規則是按照註解來過濾*/
FilterType type() default FilterType.ANNOTATION;
}
}
/*Filter中的FilterType支援過濾型別*/
public enum FilterType {
ANNOTATION, //註解
ASSIGNABLE_TYPE, //指定型別,比如指定包路徑下的某個具體類
ASPECTJ,//使用aspectj表示式
REGEX,//正規表示式
CUSTOM;//自定義
}
@ComponentScan的自定義掃描規則
- 實現TypeFilter類
/**
* 自定義過濾規則
*/
public class CustomFilterType implements TypeFilter {
/**
* @param metadataReader 獲取當前正在掃描的類的資訊
* @param metadataReaderFactory 獲取其他類的資訊
* @return
* @throws IOException
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
/*獲取當前類的註解資訊*/
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
/*獲取當前類的資訊*/
ClassMetadata classMetadata = metadataReader.getClassMetadata();
/*獲取資原始檔*/
Resource resource = metadataReader.getResource();
System.out.println("---------------->" + classMetadata.getClassName());
/*過濾類全名稱包括HelloController的類*/
if (classMetadata.getClassName().contains("HelloController")) {
return true;
}
return false;
}
}
- 配置類配置自定義掃描規則
/**
* 配置類等價於spring的配置檔案
*/
@Configuration
@ComponentScan(value = "com.sff.app",useDefaultFilters = false,
includeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM, classes = CustomFilterType.class)})
public class AppConfig {
/*給容器中註冊一個bean,型別是方法返回值,id就是方法名稱*/
@Bean
public Person person() {
return new Person("Kate", 12);
}
}
- 測試類
public class ComponentScanTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
String[] names = ctx.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
}
結果分析:
//列印出了當前掃描的類的資訊
---------------->com.sff.app.ComponentScanTest
---------------->com.sff.app.ConfigurationTest
---------------->com.sff.app.TestAnno
---------------->com.sff.app.anno.AnnoDemo
---------------->com.sff.app.anno.MyAnnotation
---------------->com.sff.app.anno.Rename
---------------->com.sff.app.bean.Person
---------------->com.sff.app.config.CustomFilterType
---------------->com.sff.app.controller.HelloController
---------------->com.sff.app.service.HelloService
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
/*過濾後容器中的類資訊*/
appConfig //主配置類
helloController
person //通過@Bean注入的