spring注解驱动开发-组件注册-@ComponentScan自动扫描&指定扫描组件

1.@ComponentScan使用

1.新建一个类ConfigComponentScan,类上加@ComponentScan(value ="springanntition.configbean");表明要扫描springanntition.configbean包下的类


@Configuration
@ComponentScan(value ="springanntition.configbean")
public class ConfigComponentScan {
    // @Bean含义:给容器中注册一个Bean;类型为返回值类型,id默认是用方法名作为id,也可以起别名称
    @Bean
    public Person personDy() {
        return new Person("ddf", 25);
    }
}

就相当于扫描此路径下,然后test包下再建立同路径名下的测试类,pom.xml要添加junit包哦

添加测试类MainTestComponentScan如下

package springannotion.configbean;

import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import springanntition.configbean.ConfigComponentScan;


public class MainTestComponentScan {
    @Test
    public void getIOCBean(){
        // 需要写上你需要的配置类哦!
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigComponentScan.class);
        // 获取bean的名字
        String[] beannames = context.getBeanDefinitionNames();
        for (String name : beannames) {
            System.out.println(name);
        }
    }
}

咱们运行一下,除了默认的容器外,标红的就是我们获取到的,configComponentScan是配置类本身的名字,mainConfig是上一篇讲解建立的配置类,以及@Bean的配置全部都获取到了。

我们再建立一个controller类和service类来测试@ComponentScan数组的方式

package anntiontest;

import org.springframework.stereotype.Controller;

@Controller
public class TeseController {
}
package anntiontest;

import org.springframework.stereotype.Service;

@Service
public class TestService {
}

到配置里更改@ComponentScan注解


@Configuration
@ComponentScan(value = {"springanntition.configbean","anntiontest"})
public class ConfigComponentScan {
    // @Bean含义:给容器中注册一个Bean;类型为返回值类型,id默认是用方法名作为id,也可以起别名称
    @Bean
    public Person personDy() {
        return new Person("ddf", 25);
    }
}

运行测试类,发现新添加的类名扫描出来了

其实这个@ComponentScan就相当于<context:component-scan>标签的使用

<?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">

    <!-- context:component-scan学习  -->
    <!-- 包扫描、只要标注了@Controller、@Service、@Repository、@Component这4个里的任意一个组件,那么他们都会自动的扫描加入到容器中 -->
    <context:component-scan base-package="springanntition.configbean"></context:component-scan>

    <!-- bean注入学习 -->
    <!-- scope="prototype" -->
    <bean id="person" class="springorgin.demo.configbean.Person">
        <!-- property是以属性注入 -->
        <property name="age" value="18"></property>
        <property name="name" value="df"></property>
    </bean>
</beans>

2.ComponentScan指定扫描与排除扫描

2.1 excludeFilters

我们也可以按照条件进行进行扫描。ctrl+点击@ComponentScan进源码

includeFilters:Filter[]数组,指定扫描时候只需要包含哪些组件

excludeFilters:是一个Filter数组,指定扫描的时候按照什么规则排除那些组件

我们在配置文件ConfigComponentScan类里加上如下配置,FilterType.ANNOTATION:这个是过滤类型,过滤类型可以有多种方式此处ANNOTATION就是按注解方式指定Controller,讲解完includeFilters在详细说Filter下的type

package springanntition.configbean;

import org.springframework.context.annotation.*;
import org.springframework.stereotype.Controller;
import springorgin.demo.configbean.Person;

@Configuration
// @ComponentScan value:指定要扫描的包,可以是单个或多个的形式
// 过滤不扫描Controller类
@ComponentScan(value = {"springanntition.configbean", "anntiontest"},excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class)
})
public class ConfigComponentScan {
    // @Bean含义:给容器中注册一个Bean;类型为返回值类型,id默认是用方法名作为id,也可以起别名称
    @Bean
    public Person personDy() {
        return new Person("ddf", 25);
    }
}

运行测试类,发现已经没有了Controller

2.2 includeFilters

咱们再来说说指定哪个注解扫描,在配置文件更改以下,添加一个useDefaultFilters的配置=false,原因是默认@ComponentScan默认是扫描全部的,在spring.xml里如果要指定扫描也是需要配置一个默认扫描为false的useDefaultFilters

@ComponentScan(value = {"springanntition.configbean", "anntiontest"}, includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class),
}, useDefaultFilters = false)

运行测试类

2.3includeFilters的Type讲解

下面我们来说以下Filter的方式有哪些?

includeFilters =Filter[] 指定扫描时候只需要包含哪些组件

FilterType.ANNOTATION:这个是注解方式,我们也实践过了

FilterType.ASSIGNABLE_TYPE:按照给定的类型,不管它的子类还是什么

FilterType.CUSTOM:自定义过滤类型,自定义类型需要实现TypeFilter

我们来实践一下FilterType.ASSIGNABLE_TYPE方式,配置类里加上如下,指定扫描@Controller并且指定扫描TestService类

@ComponentScan(value = {"springanntition.configbean", "anntiontest"}, includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class),
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = TestService.class),
}, useDefaultFilters = false)

运行测试类,我们看到TestService已经扫描到了

还有一种是自定义类型,我们来实践下,自定义方式和上面两种方式不一样,需要新创建一个类,并且实现 TypeFilter类

新建一个MyTypeFilter类,实现TypeFilter,然后根据参数获取到我们需要的信息,根据信息扫描需要的组件,如果返回true就是匹配扫描,返回false就是不匹配

package springanntition.configbean;

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 {
    /*
       metadataReader:读取到的当前正在扫描的类的信息
       metadataReaderFactory:可以获取到其他任何类信息的
    */
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
            throws IOException {
        // 获取当前类注解的信息
        AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
        // 获取当前正在扫描的类的信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        // 获取当前类的资源信息(类的路径)
        Resource resource = metadataReader.getResource();
        // 可以获取类名称
        String calssName = classMetadata.getClassName();
        System.out.println("--->" + calssName);
        // 根据类名称扫描带er字样的属性
        if (calssName.contains("er")) {
            return true;
        }
        // 返回return false就是一个都不匹配
        return false;
    }
}

扫描配置类配置如下

@ComponentScan(value = {"springanntition.configbean", "anntiontest"}, includeFilters = {
       /* @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class),
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = TestService.class),*/
        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})
}, useDefaultFilters = false)

运行出来了,包含er的都被扫描到了

咱们在ctrl+@ComponentScan点击进来以后发现有个@Repeatable,这个组件的意思是重复组件,就是说类上可以写多个@ComponentScan,限于jdk1.8哦

 @ComponentScan(value = {"springannotion", "anntiontest"})
 @ComponentScan()

如果不是JDK1.8不支持重复组件,也可以使用如下@ComponentScans来使用

@ComponentScans(value = {
      @ComponentScan(value = {"springannotion", "anntiontest"})
})

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值