Spring注解--@Configuration、@Bean、@ComponentScan的过滤规则FilterType详解

@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)//开启扫描
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
@ComponentScan是Spring框架中的注解之一,用于指定要扫描的包及其子包,以自动注册Spring容器中的Bean。它的作用是告诉Spring在指定的包中查找带有@Component注解(或其他特定注解)的类,并将其实例化为Bean,并加入到Spring容器中统一管理。 @ComponentScan可以用在@Configuration注解的类上,也可以用在普通的@Component注解的类上。当用在@Configuration注解的类上时,它会扫描指定包下的所有类并注册为Bean;当用在普通的@Component注解的类上时,它会扫描指定包下的所有类并将其作为普通Bean进行注册。 @ComponentScan可以接收一个或多个参数,常见的参数如下: - basePackages:指定要扫描的包路径,可以使用字符串数组指定多个包。例如:@ComponentScan(basePackages = {"com.example.package1", "com.example.package2"}) - basePackageClasses:指定要扫描的类所在的包,Spring会根据这些类所在的包路径进行扫描。例如:@ComponentScan(basePackageClasses = {Class1.class, Class2.class}) - includeFilters:指定要包含的过滤条件,只有符合条件的类才会被注册为Bean。例如:@ComponentScan(includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = MyAnnotation.class)) - excludeFilters:指定要排除的过滤条件,符合条件的类不会被注册为Bean。例如:@ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = MyExcludeClass.class)) 除了上述常见的参数外,还可以使用其他参数来进一步细化扫描的范围和条件。通过灵活配置@ComponentScan注解,我们可以方便地进行自动扫描和注册Bean,减少手动配置的工作量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值