02-Spring组件注册-@ComponentScan

包扫描的方式

如果没有设置包扫描路径,Spring 不会主动去注册 bean

XML方式配置包扫描

<?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 base-package="com.demon" />
</beans>

注解方式配置包扫描

会扫描包路径下所有的包含 @Component 注解的类:

  • @Controller
  • @RestController
  • @Service
  • @Repository
  • @Component
package com.demon.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * 配置类
 * @author Demon-HY
 * @date 2019-12-9
 */
@ComponentScan("com.demon")
@Configuration
public class Config {
}

简单使用举例

写几个上面提到的注解

UserController.java

package com.demon.controller;

import org.springframework.stereotype.Controller;

/**
 * @author Demon-HY
 * @date 2019-12-9
 */
@Controller
public class UserController {
}

UserService.java

package com.demon.service;

import org.springframework.stereotype.Service;

/**
 * @author Demon-HY
 * @date 2019-12-9
 */
@Service
public class UserService {
}

UserDao.java

package com.demon.dao;

import org.springframework.stereotype.Repository;

/**
 * @author Demon-HY
 * @date 2019-12-9
 */
@Repository
public class UserDao {
}

导入 Spring 测试框架需要的包

<!--测试-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

测试用例

package com.demon;

import com.demon.config.Config;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author Demon-HY
 * @date 2019-12-9
 */
public class IOCTest {

    @Test
    public void test() {
        // 通过注解方式生成 Spring 上下文
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);

        // 打印容器中注册的bean
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String name : beanDefinitionNames) {
            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
config
userController
userDao
userService
user

@ComponentScan 注解中常用参数详解

value/basePackages

指定要扫描的包

excludeFilters 排除规则

excludeFilters 里面嵌套了一个@Filter注解,用来设置多个排除规则

@Filter 注解常用参数

FilterType 过滤类型:

  • ANNOTATION: 注解
  • ASSIGNABLE_TYPE: 类型
  • ASPECTJ: ASPECTJ 表达式
  • REGEX: 正则表达式
  • CUSTOM: 自定义规则

includeFilters 包含规则,和excludeFilters正好相反

例子: 排除 @Controller 注解的类

package com.demon.config;

import com.demon.bean.User;
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;

/**
 * 配置类
 * @author Demon-HY
 * @date 2019-12-9
 */
@ComponentScan(value = "com.demon", excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
})
@Configuration
public class Config {
}

例子: 只扫描 @Controller 的类

package com.demon.config;

import com.demon.bean.User;
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;

/**
 * 配置类
 * @author Demon-HY
 * @date 2019-12-9
 */
@ComponentScan(value = "com.demon", includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
})
@Configuration
public class Config {
}

例子: 过滤 UserService 及其子类和实现类

package com.demon.config;

import com.demon.bean.User;
import com.demon.service.UserService;
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;

/**
 * 配置类
 * @author Demon-HY
 * @date 2019-12-9
 */
@ComponentScan(value = "com.demon", excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {UserService.class})
})
@Configuration
public class Config {
}

通过自定义规则过滤 bean id 包含 “User” 的类

自定义过滤规则 MyTypeFilter.java

package com.demon.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;

/**
 * 自定义 @ComponentScan 过滤规则
 * @author Demon-HY
 * @date 2019-12-9
 */
public class MyTypeFilter implements TypeFilter {

    /**
     * @param metadataReader 读取到的当前正在扫描的类的信息
     * @param metadataReaderFactory 可以获取到其他任何类信息
     */
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        // 获取当前类注解信息
        AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
        // 获取当前正在扫描的类的信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        // 获取当前类资源信息(类路径)
        Resource resource = metadataReader.getResource();

        // 获取当前类名
        String className = classMetadata.getClassName();
        if (className.contains("user")) {
            return true;
        }
        return false;
    }
}

修改配置类

package com.demon.config;

import com.demon.bean.User;
import com.demon.service.UserService;
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;

/**
 * 配置类
 * @author Demon-HY
 * @date 2019-12-9
 */
@ComponentScan(value = "com.demon", excludeFilters = {
        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})
})
@Configuration
public class Config {
}

执行上面写的那个测试用例

UserController,UserService,UserDao 都被过滤掉了,User类没有被过滤掉是因为,User是我们自己在Config.java中设置的,不会被拦截

咖啡小馆

QQ群: 823971061 点击按钮入群

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Demon-HY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值