暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

@AutoConfigurationPackage 和 @ComponentScan 有何区别?

江南一点雨 2023-05-17
402

TienChin 视频杀青啦~采用 Spring Boot+Vue3 技术栈,里边会涉及到各种好玩的技术,小伙伴们来和松哥一起做一个完成率超 90% 的项目,戳戳戳这里-->TienChin 项目配套视频来啦


面试真是越来越卷了,最近又有小伙伴在微信上问到松哥这样一个面试题,想到这两个的区别其实还有点意思,因为整一篇文章和小伙伴们捋一捋。

首先,从名字上看,这两个注解意义特别接近,@AutoConfigurationPackage
就是自动配置包,自动配置包的目的是能让系统扫描到包内的 Bean;@ComponentScan
则是组件扫描,这个松哥在之前的教程中也多次提到过了,就不再赘述了,所以这里就有一个问题,这两个注解有啥区别?

首先大家思考这样一个问题:

现在大多数项目可能都是用的 MyBatis 或者 MyBatis-Plus 这样的数据持久化框架,当我们在 Spring Boot 中使用 MyBatis 的时候,我们一般需要在 Mapper 接口上添加一个 @Mapper 注解,类似下面这样:

@Mapper
public interface UserMapper {
}

复制

或者在启动类上加 Mapper 扫描注解去统一扫描所有的 Mapper 接口,类似下面这样:

@SpringBootApplication
@MapperScan(basePackages = "org.javaboy.auto_package")
public class AutoPackageApplication {

    public static void main(String[] args) {
        SpringApplication.run(AutoPackageApplication.classargs);
    }

}

复制

平时我们都这样写,没有任何问题,现在假设我们换一个写法,假如我的类结构如下:

├── main
│   ├── java
│   │   └── org
│   │   └── javaboy
│   │   └── auto_package
│   │   ├── config
│   │   │   ├── AutoPackageApplication.java
│   │   │   └── UserController.java
│   │   ├── mapper
│   │   │   └── UserMapper.java
│   │   └── service
│   │   └── UserService.java

复制

小伙伴们看到,我把启动类和 UserController 放在一个单独的包中,UserMapper 和 UserService 也分别位于不同的包中,其中在 UserController 中注入了 UserService,在 UserService 中则注入了 UserMapper,大致上就这么一个关系。

按照我们之前对 Spring Boot 的理解,这个项目启动肯定会报错,因为默认情况下,系统扫描的 Bean 是启动类所在的包以及子包下的所有 Bean(因为 @SpringBootApplication
注解在启动类上),所以上面这个项目启动的时候,能扫描到 UserController,但是扫描不到 UserService,所以启动的时候会报错,如下:

大家看下,这意思很明确,UserService 找不到,所以启动失败。

解决这个问题的办法很简单,要么将启动类放到根包下面,这样所有的 Bean 默认就都能扫描到了,要么我们重新配置包扫描,这里我采用第二种方案,我们在启动类上加 @ComponentScan
注解,重新指定扫描的包,如下:

@SpringBootApplication
@ComponentScan(basePackages = "org.javaboy.auto_package")
public class AutoPackageApplication {

    public static void main(String[] args) {
        SpringApplication.run(AutoPackageApplication.classargs);
    }

}

复制

加上之后,我们再次启动,发现又报错了,如下:

虽然再次出错,但是跟之前的错误并不一样,这次是没找到 UserMapper 这个 Bean,说明 UserService 是找到了!

从这里我们就可以看出来,@ComponentScan
注解扫描组件是不会扫描到 @Mapper 注解的!

事实上,@ComponentScan
注解主要是扫描 Spring 家族的各种 Bean,如 @Controller、@Service、@Component、@Repository 以及由此衍生出来的一些其他的 Bean,对于 Spring 家族之外的 Bean,如 MyBatis 的 @Mapper、@MapperScan,JPA 的 @Entity 等,@ComponentScan
都扫不到!

谁能扫到呢?那就是我们今天的另外一个主角 @AutoConfigurationPackage
,这个注解其实就是专门用来扫这些第三方的各种 Bean 的。

现在,我们在项目启动上加上 @AutoConfigurationPackage
注解,并设置需要扫描的位置,如下:

@SpringBootApplication
@AutoConfigurationPackage(basePackages = "org.javaboy.auto_package")
@ComponentScan(basePackages = "org.javaboy.auto_package")
public class AutoPackageApplication {

    public static void main(String[] args) {
        SpringApplication.run(AutoPackageApplication.classargs);
    }

}

复制

此时,项目就可以成功启动了,因为 @AutoConfigurationPackage(basePackages = "org.javaboy.auto_package")
注解可以扫描到 @Mapper 注解。

当然,这里只是为了给大家演示问题,实际场景下直接在启动类上加 @MapperScan(basePackages = "org.javaboy.auto_package")
注解就可以了。因为 @MapperScan 注解是 mybatis-spring 提供的,而 @Mapper 是 MyBatis 自己提供的,两个注解的出处本身就不同。

默认情况下,Spring Boot 项目的启动注解中,实际上已经包含了 @AutoConfigurationPackage
注解,具体位置在 @SpringBootApplication
->@EnableAutoConfiguration
->@AutoConfigurationPackage
,默认该注解没有指定 basePackages 属性,表示使用启动类所在的包作为根包,扫描该包下的所有第三方 Bean,所以我们平时在 Spring Boot 中使用 MyBatis 的时候,是不需要额外加 @AutoConfigurationPackage
注解的。

经过上面问题的演示,相信小伙伴们已经搞明白了 @AutoConfigurationPackage
@ComponentScan
的区别了吧?

小结

总结一下:

  1. 两者都是用来扫描 Bean 的。
  2. @ComponentScan
    主要用来扫描和 Spring 容器相关的 Bean。
  3. @AutoConfigurationPackage
    主要用来扫描第三方的 Bean。

仅此而已。


TienChin 视频杀青啦~采用 Spring Boot+Vue3 技术栈,里边会涉及到各种好玩的技术,小伙伴们来和松哥一起做一个完成率超 90% 的项目,戳戳戳这里-->TienChin 项目配套视频来啦

本周送书活动来啦,瞧,就是下面这本,上次过后有小伙伴表示六本太少了,不够,所以松哥好说歹说,又和出版社要了六本,还是老规矩,小伙伴们随便留言,我会选出来六位幸运小伙伴!

文章转载自江南一点雨,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论