@ComponentScan 包扫描策略

xml 中配置包扫描策略

<context:component-scan base-package="com.liuzhihang"></context:component-scan>

Spring就会去自动扫描base-package对应的路径或者该路径的子包下面的java文件,如果扫描到文件中带有@Service,@Component,@Repository,@Controller等这些注解的类,则把这些类注册为bean
标签中含有多种属性, 可以排除或指定扫描策略.

@ComponentScan 注解的方式指定扫描策略

在注解配置类上添加 @ComponentScan(value = “com.liuzhihang”) 注解, 同时可以在注解中指定扫描策略

@Configuration
@ComponentScan(value = "com.liuzhihang")
public class ApplicationContextConfig {

    @Bean
    public User user() {

        System.out.println("********* ioc 容器中创建 user");
        return new User(2L, "liuzhihang", 25);
    }
}

注解会自动搜啊秒 com.liuzhihang 包下 @Service,@Component,@Repository,@Controller 注解的类.

测试及结果

junit 测试代码:

/**
 * @Description:
 * @Author: liuzhihang
 * @Date: 2018/5/15 23:06
 */
public class IOCTest {

    ApplicationContext applicationContext;

    @Before
    public void before() {
        System.out.println("开始引入配置类");
        applicationContext = new AnnotationConfigApplicationContext(ApplicationContextConfig.class);
    }

    @Test
    public void iocTest() {

        String[] names = applicationContext.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }
    }

}

控制台输出结果:

### D:\jdk1.8\bin\java.exe . . .
开始引入配置类
五月 16, 2018 3:52:17 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@47089e5f: startup date [Wed May 16 15:52:17 CST 2018]; root of context hierarchy
********* ioc 容器中创建 user
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
applicationContextConfig
userController
userDao
userService
user

Process finished with exit code 0

指定@ComponentScan解析规则

1.excludeFilters = {} 排除过滤器
2.includeFilters = {} 包含过滤器, 生效时必须禁用默认规则 useDefaultFilters = false

排除被Controller注解标注的类
@ComponentScan(value = "com.liuzhihang",
        excludeFilters = {
                @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class),
                @ComponentScan.Filter(type = FilterType.CUSTOM, classes = MyComponentScanFilter.class)
        })

FilterType 介绍:

FilterType 介绍
ANNOTATION 按照注解过滤
ASSIGNABLE_TYPE 按照类型过滤
ASPECTJ 使用ASPECTJ表达式
REGEX 使用正则指定
CUSTOM 使用自定义规则

当使用自定义规则时, MyComponentScanFilter 类介绍

/**
 * @author liuzhihang
 * @date 2018/5/16 16:30
 */
public class MyComponentScanFilter implements TypeFilter {

    /**
     *
     * @param metadataReader 读取到的当前正在扫描类的信息
     * @param metadataReaderFactory 获取到其他类的信息
     * @return
     * @throws IOException
     */
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {

        // 获取当前扫描的类信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        String className = classMetadata.getClassName();
        System.out.println("当前扫描的类信息为: " + className);

        // 获取当前类的注解
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        // 判断是否包含 Service 注解
        System.err.println(annotationMetadata.hasAnnotation(Service.class.getName()));

        // 获取到其他类的信息
        // MetadataReader metadataReader1 = metadataReaderFactory.getMetadataReader(UserDao.class.getName());
        // AnnotationMetadata annotationMetadata1 = metadataReader1.getAnnotationMetadata();
        // System.err.println(annotationMetadata1.hasAnnotation(Repository.class.getName()));

        return false;
    }
}

   转载规则


《@ComponentScan 包扫描策略》 liuzhihang 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录