【Spring注解】2.@ComponentScan注解

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

2.@ComponentScan

1.使用xml配置包扫描的方式

<!--包扫描,只要标注了@Controller/@Service/@Repository/@Component就可以被扫描到-->
<context:component-scan base-package="com.ooyhao"></context:component-scan>

【Spring注解】2.@ComponentScan注解_Spring注解

 

定义相应的Controller,service,dao层,并用相应的注解进行标注。

2.使用注解方式进行包扫描

//配置类==配置文件
@ComponentScan(value = {"com.ooyhao"})//可以定义多个。
@Configuration //告诉Spring这是一个配置类
public class MainConfig {

// 给容器中注册一个Bean,类型就是返回值的类型,id默认是用方法名作为id、
@Bean("person")
public Person person01(){
return new Person("李四",20);
}
}

注意:

xml方式,<context:component-scan></context:component-scan>是配置在beans.xml文件中的,所以只需要在MainConfig类上用@ComponentScan(value/basePackages="")来进行扫描。(value与basePackages作用一致)。

可以定义多个:(部分源码)

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {

/**
* Alias for {@link #basePackages}.
* <p>Allows for more concise annotation declarations if no other attributes
* are needed — for example, {@code @ComponentScan("org.my.pkg")}
* instead of {@code @ComponentScan(basePackages = "org.my.pkg")}.
*/
@AliasFor("basePackages")
String[] value() default {};

/**
* Base packages to scan for annotated components.
* <p>{@link #value} is an alias for (and mutually exclusive with) this
* attribute.
* <p>Use {@link #basePackageClasses} for a type-safe alternative to
* String-based package names.
*/
@AliasFor("value")
String[] basePackages() default {};

/**
* Type-safe alternative to {@link #basePackages} for specifying the packages
* to scan for annotated components. The package of each class specified will be scanned.
* <p>Consider creating a special no-op marker class or interface in each package
* that serves no purpose other than being referenced by this attribute.
*/
Class<?>[] basePackageClasses() default {};

测试代码:

@Test
public void testComponent(){
AnnotationConfigApplicationContext context = new
AnnotationConfigApplicationContext(MainConfig.class);
String[] names = context.getBeanDefinitionNames();
for(String name:names){
System.out.println(name);
}
}

结果:

 

【Spring注解】2.@ComponentScan注解_System_02

 

3.@Component的扫描规则

1.FilterType的源码(取值):

public enum FilterType {
ANNOTATION, //按照注解的方式
ASSIGNABLE_TYPE, //按照给定的类型
ASPECTJ, //按照ASPECTJ表达式
REGEX, //按照正则表达式
CUSTOM //自定义
}

2.@Componenet的源码

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class) //可以重复,说明可以写多个ComponentScan
public @interface ComponentScan {

@AliasFor("basePackages")
String[] value() default {};

@AliasFor("value")
String[] basePackages() default {};

Class<?>[] basePackageClasses() default {};

Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;

boolean useDefaultFilters() default true;

Filter[] includeFilters() default {};

Filter[] excludeFilters() default {};

boolean lazyInit() default false;

@Retention(RetentionPolicy.RUNTIME)
@Target({})
@interface Filter {

FilterType type() default FilterType.ANNOTATION;

@AliasFor("classes")
Class<?>[] value() default {};

@AliasFor("value")
Class<?>[] classes() default {};

String[] pattern() default {};

}

}

3.MainConfig.java(排除)

//配置类==配置文件
@ComponentScan(value = {"com.ooyhao"},excludeFilters = {
@Filter(type = FilterType.ANNOTATION,value = {Controller.class}),
@Filter(type = FilterType.ASSIGNABLE_TYPE,value = {BookService.class})
})
@Configuration //告诉Spring这是一个配置类
public class MainConfig {

// 给容器中注册一个Bean,类型就是返回值的类型,id默认是用方法名作为id、
@Bean("person")
public Person person01(){
return new Person("李四",20);
}

}

(排除了@Controller标注的,以及BookService类型的)

【Spring注解】2.@ComponentScan注解_自定义_03

 

4.MainConfig.java(包含)

xml方式:

<!--包扫描,只要标注了@Controller/@Service/@Repository/@Component就可以被扫描到-->
<context:component-scan base-package="com.ooyhao" use-default-filters="false"></context:component-scan>
<!--需要使用use-default-filters来禁用默认的扫描规则-->

注解方式:

//配置类==配置文件
/*@ComponentScan(value = {"com.ooyhao"},excludeFilters = {
@Filter(type = FilterType.ANNOTATION,value = {Controller.class}),
@Filter(type = FilterType.ASSIGNABLE_TYPE,value = {BookService.class})
})*/
@ComponentScan(basePackages = "com.ooyhao",includeFilters = {
@Filter(type = FilterType.ANNOTATION,value = {Controller.class})
},useDefaultFilters = false)
@Configuration //告诉Spring这是一个配置类
public class MainConfig {

(只包含@Controller标注的)

【Spring注解】2.@ComponentScan注解_Spring注解_04

 

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class) //可以重复,说明可以写多个ComponentScan
public @interface ComponentScan {

可同时写多个@ComponentScan(JDK1.8)。也可以使用@ComponentScans();

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface ComponentScans {
ComponentScan[] value();
}

(配置多个@ComponentScan)

@ComponentScan(basePackages = "com.ooyhao",includeFilters = {
@Filter(type = FilterType.ANNOTATION,value = {Controller.class})//(按照注解)
},useDefaultFilters = false)
@ComponentScan(basePackages = "com.ooyhao",includeFilters = {
@Filter(type = FilterType.ANNOTATION,value = {Service.class})//包括子类(按照指定类型)
},useDefaultFilters = false)
@Configuration //告诉Spring这是一个配置类
public class MainConfig {

【Spring注解】2.@ComponentScan注解_Spring_05

 

5.自定义扫描规则

通过实现TypeFilter接口来自定义扫描规则的Filter

public interface TypeFilter {

/**
* @param metadataReader :当前正在扫描的类的信息
* @param metadataReaderFactory :可以获取到其他类的信息
*/
boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException;
}

自定义扫描过滤器

public class MyTypeFilter implements TypeFilter{

/**
* @param metadataReader :当前正在扫描的类的信息
* @param metadataReaderFactory :可以获取到其他类的信息
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//获得当前类注解信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获得当前类资源信息(类的路径等)
Resource resource = metadataReader.getResource();
// String className = classMetadata.getClassName();
System.out.println(annotationMetadata.getAnnotationTypes());//获得注解类型
System.out.println(resource.getURL());//获得资源路径
System.out.println(classMetadata.getClassName());//获得类名

if(classMetadata.getClassName().contains("er")) {
return true;
}
return false;
}
}

在Config.java上配置

@ComponentScan(basePackages = "com.ooyhao",includeFilters = {
/*@Filter(type = FilterType.ANNOTATION,value = {Controller.class}),*/
@Filter(type = FilterType.CUSTOM,value = {MyTypeFilter.class})
},useDefaultFilters = false)
@Configuration //告诉Spring这是一个配置类
public class MainConfig {

【Spring注解】2.@ComponentScan注解_自定义_06

 

总结:

为什么myTypeFilter会被扫描到:

由于我们扫描的基本包是com.ooyhao,所有在这个基本包下面的所有的类都会被扫描到进行过滤,而只有上述结果中的三个是包含"er"的,所有就会被扫描到。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Spring