二、Spring注解:@ComponentScan

1. XML配置包扫描路径

​ 在传统的Spring程序中,我们会在XML文件中配置包扫描路径,将扫描到的被@Controller ,@Serrvice,@Repository,@Component等注解注释的组件加入IOC容器中去。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 包扫描,只要标注了@Controller ,@Serrvice,@Repository,@Component 自动扫描加入容器中 -->
    <context:component-scan base-package="com.baiding"/>
</beans>

​ 使用JavaConfig方式配置的话,我们可以用@ComponentScan注解替换上述XML配置。

2. @ComponentScan的使用
@ComponentScan:在容器中注册组件的第二种方式,包扫描加上给组件标注注解—@Controller、@Service、@Component等

​ @ComponentScan有几个属性,其中value指定扫描的包路径,includeFilters指定扫描哪些组件,excludeFilters指定不扫描哪些组件,useDefaultFilters默认的过滤规则是开启的,若要使用includeFilters,则要将useDefaultFilters的值置为false。

配置类:

@Configuration
@ComponentScan(value = "com.baiding")
public class BeanConfig {

    /**
     * 给容器中注册一个bean 类型为返回值的类型 id默认为方法名或者直接用属性name配置id
     * @return
     */
    @Bean(name = "wangwu")
    public Person person(){
        return new Person("wangwu",22);
    }
}

测试类:

    @Test
    void test03(){
        ApplicationContext ac = new AnnotationConfigApplicationContext(BeanConfig.class);
        // 得到所有Bean的name
        String[] names = ac.getBeanDefinitionNames();
        for(String name :names){
            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
beanConfig
personController
personDAO
personService
wangwu

结果上面的是IOC容器自己要装配的组件,下面的就是配置的扫描路径下扫出来的bean.

3. 指定扫描过滤规则
3.1 @excludeFilters

​ 当使用excludeFilters指定不扫描哪些内容的时候,我们需要用到@Filter注解,这是一个位于@ComponentScan注解内部的一个注解,用来配置过滤规则。@Filter有一个type属性,它的值是一个枚举值,用来说明过滤的方式 — 按照什么规则进行过滤。

FilterType.ANNOTATION:按照注解

FilterType.ASSIGNABLE_TYPE:按照给定的类型

FilterType.ASPECTJ:使用ASPECTJ表达式

FilterType.REGEX:使用正则指定

FilterType.CUSTOM:使用自定义规则

例如:我们需要过滤所有的使用Controller注解和Service注解的类,采用FilterType.ANNOTATION过滤

@Configuration
@ComponentScan(value = "com.baiding",
        excludeFilters = {
            @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class, Service.class})
        }
)
public class BeanConfig {

    /**
     * 给容器中注册一个bean 类型为返回值的类型 id默认为方法名或者直接用属性name配置id
     * @return
     */
    @Bean(name = "wangwu")
    public Person person(){
        return new Person("wangwu",22);
    }
}

结果:

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
beanConfig
personDAO
wangwu
3.2 @includeFilters

​ includeFilters指定扫描的时候只需要包含哪些组件,它的使用方式和excludeFilters基本一样,只是在使用includeFilters时,我们需要关闭默认的扫描规则,即将useDefaultFilters的值置为false.

例子:使用FilterType.ANNOTATION规则制定只扫描@Controller注解的组件,

​ 使用FilterType.ASSIGNABLE_TYPE按照给定的类型去扫描注册组件(这时候不需要给定的类型有任何注解注释都会被注册到容器中)。

@Configuration
@ComponentScan(value = "com.baiding",
        includeFilters = {
            @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class}),
            @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, 
                                                        classes = {PersonService.class})
        },
        useDefaultFilters = false
)
public class BeanConfig {

    /**
     * 给容器中注册一个bean 类型为返回值的类型 id默认为方法名或者直接用属性name配置id
     * @return
     */
    @Bean(name = "wangwu")
    public Person person(){
        return new Person("wangwu",22);
    }
}

结果:

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
beanConfig
personController
personService
wangwu

其中 personDAO组件都没有被扫描注册到IOC容器中去。

3.3 自定义过滤规则

​ FilterType枚举有一个值为FilterType.CUSTOM ,它表示以自定义的规则进行组件的扫描。首先你要定义一个实现TypeFilter接口的类,在其中实现过滤规则的匹配。

实现类:

public class ServiceFilterType implements TypeFilter {
    /**
     * @param metadataReader
     *          读取到当前正在扫描的类的信息
     * @param metadataReaderFactory
     *          能够获取到其他任何类的信息
     * @return
     *          返回true的话,说明匹配成功
     * @throws IOException
     */
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        // 获取当前类注解的信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        // 获取当前正在扫描的类的信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        // 获取当前类资源(类的路径)
        Resource resource = metadataReader.getResource();

        //获取当前扫描类的完整类名 com.baiding.filter.ServiceFilterType
        String className = classMetadata.getClassName();

        return className.contains("PersonService");
    }
}

配置类:

@Configuration
@ComponentScan(value = "com.baiding",
        includeFilters = {
                @ComponentScan.Filter(type = FilterType.CUSTOM, 
                                        classes = {ServiceFilterType.class})
        },
        useDefaultFilters = false
)
public class BeanConfig {

    /**
     * 给容器中注册一个bean 类型为返回值的类型 id默认为方法名或者直接用属性name配置id
     * @return
     */
    @Bean(name = "wangwu")
    public Person person(){
        return new Person("wangwu",22);
    }
}

结果:

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
beanConfig
personService
wangwu

结果中只扫描到了personService这一个组件

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值