组件注册(3)-包扫描

144 阅读1分钟

通过 @ComponentScan@Bean向Spring容器注册组件

@ComponentScan默认启用对使用@Component@Repository@Service@Controller注释的类的自动检测,加入到容器中


  1. 初始化maven项目,详情见:组件注册(1)-XML方式 步骤1

  2. 新建类Person.javaPersonController.javaPersonDao.javaPersonService.java

    @Component
    public class Person {
        private String name;
        private Integer age;
    }
    
    @Controller
    public class PersonController {
    }
    
    @Service
    public class PersonService {
    }
    
    @Repository
    public class PersonDao {
    }
    
    
  3. 新建配置文件MainConfig.java

@Configuration
@ComponentScan(value = "com.example")
public class MainConfig {
}

@ComponentScan常用属性:

  • value:包扫描路径,同basePackages,此处com.examplePerson所在包路径
  • basePackageClasses:扫描指定的每个类的包
  • includeFilters:指定哪些类型符合组件扫描条件,过滤器类型FilterType有以下5种
    • ANNOTATION:注解
    • ASSIGNABLE_TYPE 指定类型
    • ASPECTJ aspectj表达式
    • REGEX 正则表达式
    • CUSTOM 自定义过滤器
  • excludeFilters:指定哪些类型不符合组件扫描条件
  • useDefaultFilters:指示是否应启用对使用@Component@Repository@Service@Controller注释的类的自动检测,默认为true
  1. 编写测试类

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String beanName : beanDefinitionNames) {
            System.out.println(beanName);
        }
    }
    

    控制台打印结果:

    scanTest.png

@ComponentScan复杂用法

@ComponentScan(value = "com.example",
        excludeFilters = {
            @ComponentScan.Filter(type = FilterType.ANNOTATION, value ={Controller.class})
        },
        includeFilters = { 
                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = {PersonService.class}),
                @ComponentScan.Filter(type = FilterType.CUSTOM, value = {MyTypeFilter.class})
        },
        useDefaultFilters = false)
public class MainConfig {
}

自定义过滤器(实现TypeFilter接口):

public class MyTypeFilter implements TypeFilter {

    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) {
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        String className = classMetadata.getClassName();
        //扫描名称包含Dao的bean
        if (className.contains("Dao")) {
            return true;
        }
        return false;
    }
}

控制台打印结果:

scanTest2.png

代码解释:

  • 扫描com.example包: value = "com.example"

  • 排除被@Controller注解的类: excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value ={Controller.class})}

  • 指定扫描条件:扫描指定类PersonService,根据自定义过滤器MyTypeFilter进行扫描:

includeFilters = { @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = {PersonService.class}), @ComponentScan.Filter(type = FilterType.CUSTOM, value = {MyTypeFilter.class}) }

  • 不启动自动检测: useDefaultFilters = false

代码地址