一、@ComponentScan用法介绍

@ComponentScan很多人都知道它是用来扫描知道包路径下的组件,并把它们注册到Spring容器中。

@ComponentScan它看着挺简单,但是它有很多参数,功能很强大,其中有很多细节需要注意。

下面我讲由浅入深地介绍@ComponentScan。

1. value和basePackages

value和basePackages的作用是一样的,它们互为别名,给他们设置成某包名路径,这样Spring项目启动时就会加载该包和其子包的带有特定注解的类到Spring容器中。这些注解有@Component、@Bean、@Controller、@Service、@Repository等等。

1.1 创建目录结构

在这里插入图片描述

1.2 config包下配置类SpringConfiguration

注意@ComponentScan({“config”})指定扫描config包

package config;

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

@Configuration
@ComponentScan({"config"})
public class SpringConfiguration {
}

1.3 server包下业务接口和类

UserService 接口

package service;

public interface UserService {
    void saveUser();
}

UserServiceImpl 实现类
注意给UserServiceImpl加了注解@Service(“userService”)

package service.impl;

import org.springframework.stereotype.Service;
import service.UserService;

@Service("userService")
public class UserServiceImpl implements UserService {

    @Override
    public void saveUser() {
        System.out.println("保存了用户");
    }
}

1.4 编写测试类

public class ComponentScanTest {
    public static void main(String[] args) {
        //创建容器
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext("config");

        SpringConfiguration bean1 = ac.getBean(SpringConfiguration.class);
        System.out.println(bean1);
        
        Object bean2 = ac.getBean("userService");
        System.out.println(bean2);
    }
}

1.5 运行结果分析

在这里插入图片描述
从运行结果来看,分为2个部分

  • 获取到了SpringConfiguration的Bean
  • 没有获取到userService

因为@ComponentScan({“config”})它扫描的是config包及其子包,而service包和config包是并列的,所以不会扫描到userService。

1.6 对@ComponentScan修改

@ComponentScan的value添加的是数组,所以可以再添加一个"service"

@Configuration
@ComponentScan({"config", "service"})
public class SpringConfiguration {
}

因为value和basePackages 是等同的,所以也可以写成如下

@Configuration
@ComponentScan(basePackages = {"config", "service"})
public class SpringConfiguration {
}

运行结果如下:
可以看出userService这个实力也加载了。

config.SpringConfiguration$$EnhancerBySpringCGLIB$$e3e5d8ab@14dd9eb7
service.impl.UserServiceImpl@52e6fdee

2. basePackageClasses的作用

basePackageClasses 用来指定某个类所在 包 及 其 子 包 下 \color{red}{包及其子包下} 的所有组件。
下面通过例子来说明basePackageClasses 的作用。

2.1 添加几个类

在这里插入图片描述

2.2 添加几个dao类

d a o . e s \color{red}{dao.es} dao.es包下:

@Repository("esDeptDao")
public class DeptDao {
}
@Repository("esUserDao")
public class UserDao {
}

d a o . e s . o l d \color{red}{dao.es.old} dao.es.old包下:

@Repository("oldEsUserDao")
public class UserDao {
}

mysql包下:
d a o . m y s q l \color{red}{dao.mysql} dao.mysql包下:

@Repository("mysqlUserDao")
public class UserDao {
}

2.3 给@ComponentScan添加basePackageClasses

给@ComponentScan添加basePackageClasses = DeptDao.class

注意:这里import的是 d a o . e s . D e p t D a o \color{red}{dao.es.DeptDao} dao.es.DeptDao

dao.es.DeptDao属于dao.es包,那么就会导入dao.es包和其子包dao.es.old包下的所有组件。

package config;

//注意这个import
import dao.es.DeptDao;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Co
nfiguration
@ComponentScan(basePackages = {"config", "service"}, basePackageClasses = DeptDao.class)
public class SpringConfiguration {
}

2.4 验证导入的包

public class ComponentScanTest {
    public static void main(String[] args) {
        //创建容器
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext("config");

        String[] beanDefinitionNames = ac.getBeanDefinitionNames();
        for (int i= 0; i < beanDefinitionNames.length; i++){
            System.out.println(beanDefinitionNames[i]);
        }
    }
}

输出如下:

springConfiguration
userService
esDeptDao
esUserDao
oldEsUserDao

说明basePackageClasses起到作用的是下面红框的几个类
在这里插入图片描述

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐