Spring之TypeFilter

TypeFilter, 望名思义,根据类型进行过滤。它是一个接口,有且只有一个match方法需要实现。
@FunctionalInterface
public interface TypeFilter {
    boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException;
}

它一般使用在哪些场合呢?

        答:可能有很多场合,但我目前只知道一个,那就是用于Bean的自动扫描加载。

它又如何使用呢?

        答:有一个注解会使用它,那就是@ComponentScan注解,它有一个属性:includeFilters;需要指定类型为Filter的参数。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
	@AliasFor("basePackages")
	String[] value() default {};

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

	Class[] basePackageClasses() default {};

	Class nameGenerator() default BeanNameGenerator.class;

	Class 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 {};

	}

}

下来,给大家一个示例:

1. 先定义一个实现TypeFilter接口的类

import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

import java.io.IOException;

public class MyTypeFilter 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();

        String className = classMetadata.getClassName();

        System.out.println("---: " + className);
           
        //类名包含Service的类都会被装载为Bean
        if (className.contains("Service")){
            return true;
        }

        return false;
    }
}

2. 其次,注册一个配置类。

这个配置类指定了扫描的根目录(value="xxx"字段),并且,过滤方式是MyTypeFilter类(classes =xxx),也就是我们自定义的类。

使用默认过滤器为true,也就是使用@Component, @Service,  @Controller注解的类也会被注册到实例中。

@ComponentScan(value = "com.cosseen.bean", includeFilters = {
                @ComponentScan.Filter(type = FilterType.CUSTOM, classes = MyTypeFilter.class)
        }, useDefaultFilters = true)
public class MyFilterConfig {
}

3. 常见一个App类,调用配置类加载Bean。

public class AppFilter {
    public static void main(String[] args){
        ApplicationContext ctx = new AnnotationConfigApplicationContext(MyFilterConfig.class);
        String[] names = ctx.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }
    }
}

4. 结果:

在com.cosseen.bean目录下的类名包含Service的类,会被自动装载到上下文中。使用传统注解的组件也会自动装载到上下文中。

你可能感兴趣的:(spring,java,后端)