欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring注解[email protected]、@Bean、@ComponentScan的过滤规则FilterType详解

程序员文章站 2022-05-21 22:38:07
...

@Configuration和@Bean

从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。

注意:@Configuration注解的配置类有如下要求:

  • @Configuration不可以是final类型;
  • @Configuration不可以是匿名类;
  • 嵌套的configuration必须是静态类。
//@Configuration告诉Spring这是一个配置类
@Configuration
public class MainConfig {

    //给容器中注册一个Bean,类型为返回值的类型,方法名作为id;也可以指定id:@Bean("id")
    @Bean
    public Person person(){
        return new Person("zhangsan", 18);
    }
}
public class MainTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig.class);
        Person person = (Person) ac.getBean("person");
        System.out.println(person);
        //获取person的类型
        String[] beanNamesForType = ac.getBeanNamesForType(Person.class);
        for(String name: beanNamesForType){
            System.out.println(name);
        }
    }
}
Person{name='zhangsan', age=18}
person

@ComponentScan

  • basePackages与value: 用于指定包的路径,进行扫描

  • basePackageClasses: 用于指定某个类的包的路径进行扫描

  • nameGenerator: bean的名称的生成器

  • useDefaultFilters: 是否开启对@Component,@Repository,@Service,@Controller的类进行检测

  • includeFilters: 包含的过滤条件

    • FilterType.ANNOTATION:按照注解过滤
    • FilterType.ASSIGNABLE_TYPE:按照给定的类型
    • FilterType.ASPECTJ:使用ASPECTJ表达式
    • FilterType.REGEX:正则
    • FilterType.CUSTOM:自定义规则
  • excludeFilters: 排除的过滤条件,用法和includeFilters一样

示例:
在容器中注册Controller、service和dao

package pers.zhang.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import pers.zhang.bean.Person;

//@Configuration告诉Spring这是一个配置类
@Configuration
@ComponentScan(value = "pers.zhang")//开启扫描
public class MainConfig {

    //给容器中注册一个Bean,类型为返回值的类型,方法名作为id;也可以指定id:@Bean("id")
    @Bean
    public Person person(){
        return new Person("zhangsan", 18);
    }
}

测试:

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

输出:

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
mainConfig
bookController
bookDao
bookService
person

使用excludeFilters和includeFilters过滤扫描

Filter中type的类型

  • ANNOTATION:注解类型
  • ASSIGNABLE_TYPE:指定的类型
  • ASPECTJ:按照Aspectj的表达式,基本上不会用到
  • REGEX:按照正则表达式
  • CUSTOM:自定义规则
@ComponentScan(value = "pers.zhang", excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class})
})//开启扫描

//过滤掉Controller和Service注解的Bean
//excludeFilters参数为Filter数组,type为过滤规则

输出:

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
mainConfig
bookDao
person

@ComponentScan(value = "pers.zhang", includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
}, useDefaultFilters = false)//开启扫描

//过滤:只包含Controller
//useDefaultFilters默认为true,改为false

输出:

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
mainConfig
bookController
person

通过类型指定过滤规则:

@ComponentScan(value = "pers.zhang", includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {BookService.class})
}, useDefaultFilters = false)//开启扫描
//所有BookService类型(包括子类)都在扫描的时候添加为Bean

输出:

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
mainConfig
bookController
bookService			//被扫描进来
person

自定义过滤规则
写一个TypeFilter的实现类:

package pers.zhang.config;

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 {

    @Override   //MetadataReader:当前正在扫描的类的信息;    MetadataReaderFactory:可以获取到其它任何类信息
    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);
        //类名不包含er,则注册为Bean
        if(!className.contains("er")){
            return true;
        }
        return false;
    }
}
@ComponentScan(value = "pers.zhang", includeFilters = {
//        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),
//        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {BookService.class}),
        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})
}, useDefaultFilters = false)//开启扫描
相关标签: Spring 注解