@SpringBootApplication注解包扫描问题

遇到的问题:看黑马JavaWeb课程时,这里要进行@ComponentScan组件扫描或者@Import导入,但是在分模块开发中却不需要进行组件扫描

答案:SpringBoot项目中的@SpringBootApplication注解,具有包扫描的作用,但是它只会扫描启动类所在的当前包以及子包。也就是下图两个位置不同。

在这里插入图片描述

准备工作:在Idea中导入"资料\03. 自动配置原理"下的itheima-utils工程

问题引入

1、在SpringBoot项目 spring-boot-web-config2 工程中,通过坐标引入itheima-utils依赖
在这里插入图片描述

@Component
public class TokenParser {
    public void parse(){
        System.out.println("TokenParser ... parse ...");
    }
}

2、在测试类中,添加测试方法

@SpringBootTest
public class AutoConfigurationTests {

    @Autowired
    private ApplicationContext applicationContext;


    @Test
    public void testTokenParse(){
        System.out.println(applicationContext.getBean(TokenParser.class));
    }

    //省略其他代码...
}

3、执行测试方法
在这里插入图片描述

异常信息描述: 没有com.example.TokenParse类型的bean

说明:在Spring容器中没有找到com.example.TokenParse类型的bean对象

思考:引入进来的第三方依赖当中的bean以及配置类为什么没有生效?

  • 原因在我们之前讲解IOC的时候有提到过,在类上添加@Component注解来声明bean对象时,还需要保证@Component注解能被Spring的组件扫描到。
  • SpringBoot项目中的@SpringBootApplication注解,具有包扫描的作用,但是它只会扫描启动类所在的当前包以及子包。
  • 当前包:com.itheima, 第三方依赖中提供的包:com.example(扫描不到)
    那么如何解决以上问题的呢?
  • 方案1:@ComponentScan 组件扫描
  • 方案2:@Import 导入(使用@Import导入的类会被Spring加载到IOC容器中)

GPT4-o的回答

问答一

拾叶: 启动类到底会扫描什么?

gpt-4o: Spring Boot 的启动类默认会扫描启动类所在包及其子包中的所有组件。这是因为 @SpringBootApplication 注解本身包含了 @ComponentScan 注解,默认扫描启动类所在包及其子包。

@SpringBootApplication 注解

@SpringBootApplication 是一个复合注解,它包含了以下几个注解:

  • @SpringBootConfiguration
  • @EnableAutoConfiguration
  • @ComponentScan

其中,@ComponentScan 是负责组件扫描的注解,它默认会扫描启动类所在包及其子包。

具体扫描范围

假设你的启动类位于 com.example.skyserver 包下:

package com.example.skyserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SkyServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(SkyServerApplication.class, args);
    }
}

在这种情况下,Spring Boot 会默认扫描 com.example.skyserver 包及其子包中的所有组件。

如何扩展扫描范围

如果你需要扫描其他包中的组件(例如,跨模块扫描),你可以使用 @ComponentScan 注解来指定其他包:

package com.example.skyserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan(basePackages = {"com.example.skycommon", "com.example.skyserver"})
public class SkyServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(SkyServerApplication.class, args);
    }
}

项目结构示例

假设你的项目结构如下:

sky-take-out
│
├── sky-common
│   └── src/main/java/com/example/skycommon
│       └── config
│           └── AliOssProperties.java
│
├── sky-pojo
│   └── src/main/java/com/example/skypojo
│       └── entity
│           └── SomeEntity.java
│
├── sky-server
│   └── src/main/java/com/example/skyserver
│       └── SkyServerApplication.java
│       └── controller
│           └── SomeController.java
│
├── pom.xml

在这种情况下,如果 SkyServerApplication 类位于 com.example.skyserver 包下,并且你没有使用 @ComponentScan@Import 注解,Spring Boot 只会扫描 com.example.skyserver 包及其子包中的组件。

依赖管理

确保 sky-server 模块的构建文件(如 Maven 的 pom.xml 或 Gradle 的 build.gradle)中正确地声明了对 sky-commonsky-pojo 模块的依赖,这样可以确保这些模块中的类在运行时被加载到类路径中。

Maven示例

<!-- sky-server/pom.xml -->
<dependencies>
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>sky-common</artifactId>
        <version>1.0.0</version>
    </dependency>
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>sky-pojo</artifactId>
        <version>1.0.0</version>
    </dependency>
</dependencies>

总结

Spring Boot 启动类默认会扫描启动类所在包及其子包中的组件。如果你需要跨模块扫描其他包中的组件,可以显式使用 @ComponentScan 注解来指定要扫描的包。同时,确保正确配置模块之间的依赖关系,以便类路径中包含所有必要的类。

问答二

拾叶: 假设你的启动类位于 com.example包下呢,会扫描哪些?

gpt-4o: 如果你的启动类位于 com.example 包下,Spring Boot 默认会扫描 com.example 包及其子包中的所有组件。这是因为 @SpringBootApplication 注解包含了 @ComponentScan 注解,默认扫描启动类所在包及其子包。

示例项目结构

假设你的项目结构如下:

sky-take-out
│
├── sky-common
│   └── src/main/java/com/example/skycommon
│       └── config
│           └── AliOssProperties.java
│
├── sky-pojo
│   └── src/main/java/com/example/skypojo
│       └── entity
│           └── SomeEntity.java
│
├── sky-server
│   └── src/main/java/com/example/skyserver
│       └── controller
│           └── SomeController.java
│
├── src/main/java/com/example
│   └── SkyServerApplication.java
│
├── pom.xml

启动类示例

假设启动类位于 com.example 包下:

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SkyServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(SkyServerApplication.class, args);
    }
}

扫描范围

在这种情况下,Spring Boot 会默认扫描 com.example 包及其所有子包中的所有组件。这意味着以下包中的组件都会被扫描到:

  • com.example
  • com.example.skycommon
  • com.example.skypojo
  • com.example.skyserver
  • 以及其他任何 com.example 包下的子包

组件示例

假设你有以下组件:

AliOssProperties 类在 sky-common 模块中:
package com.example.skycommon.config;

import org.springframework.stereotype.Component;

@Component
public class AliOssProperties {
    // 类的代码
}
SomeEntity 类在 sky-pojo 模块中:
package com.example.skypojo.entity;

public class SomeEntity {
    // 类的代码
}
SomeController 类在 sky-server 模块中:
package com.example.skyserver.controller;

import com.example.skycommon.config.AliOssProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SomeController {

    @Autowired
    private AliOssProperties aliOssProperties;

    // 控制器方法
}

依赖管理

确保 sky-server 模块的构建文件(如 Maven 的 pom.xml 或 Gradle 的 build.gradle)中正确地声明了对 sky-commonsky-pojo 模块的依赖,以确保这些模块中的类在运行时被加载到类路径中。

Maven示例

<!-- sky-server/pom.xml -->
<dependencies>
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>sky-common</artifactId>
        <version>1.0.0</version>
    </dependency>
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>sky-pojo</artifactId>
        <version>1.0.0</version>
    </dependency>
</dependencies>

总结

如果你的启动类位于 com.example 包下,Spring Boot 默认会扫描 com.example 包及其所有子包中的组件。这种默认行为使得你不需要显式地使用 @ComponentScan 注解来指定要扫描的包,除非你有特殊的扫描需求。确保正确配置模块之间的依赖关系,以便类路径中包含所有必要的类。

问答三

拾叶: 启动类在这个目录sky-server/src/main/java/com/example

gpt-4o: 如果启动类位于 sky-server/src/main/java/com/example 目录下,Spring Boot 默认会扫描 com.example 包及其所有子包中的组件。

项目结构

假设你的项目结构如下:

sky-take-out
│
├── sky-common
│   └── src/main/java/com/example/skycommon
│       └── config
│           └── AliOssProperties.java
│
├── sky-pojo
│   └── src/main/java/com/example/skypojo
│       └── entity
│           └── SomeEntity.java
│
├── sky-server
│   └── src/main/java/com/example
│       └── SkyServerApplication.java
│       └── skyserver
│           └── controller
│               └── SomeController.java
│
├── pom.xml

启动类示例

假设启动类位于 com.example 包下:

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SkyServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(SkyServerApplication.class, args);
    }
}

默认扫描范围

在这种情况下,Spring Boot 会默认扫描 com.example 包及其所有子包中的所有组件。这意味着以下包中的组件都会被扫描到:

  • com.example
  • com.example.skycommon
  • com.example.skypojo
  • com.example.skyserver
  • 以及其他任何 com.example 包下的子包

组件示例

AliOssProperties 类在 sky-common 模块中:
package com.example.skycommon.config;

import org.springframework.stereotype.Component;

@Component
public class AliOssProperties {
    // 类的代码
}
SomeEntity 类在 sky-pojo 模块中:
package com.example.skypojo.entity;

public class SomeEntity {
    // 类的代码
}
SomeController 类在 sky-server 模块中:
package com.example.skyserver.controller;

import com.example.skycommon.config.AliOssProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SomeController {

    @Autowired
    private AliOssProperties aliOssProperties;

    // 控制器方法
}

依赖管理

确保 sky-server 模块的构建文件(如 Maven 的 pom.xml 或 Gradle 的 build.gradle)中正确地声明了对 sky-commonsky-pojo 模块的依赖,以确保这些模块中的类在运行时被加载到类路径中。

Maven示例

<!-- sky-server/pom.xml -->
<dependencies>
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>sky-common</artifactId>
        <version>1.0.0</version>
    </dependency>
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>sky-pojo</artifactId>
        <version>1.0.0</version>
    </dependency>
</dependencies>

总结

如果启动类位于 sky-server/src/main/java/com/example 目录下,Spring Boot 会默认扫描 com.example 包及其所有子包中的组件。因此,com.example.skycommoncom.example.skypojo 包中的组件也会被扫描并注册到Spring上下文中。这种默认行为使得你不需要显式地使用 @ComponentScan 注解来指定要扫描的包,除非你有特殊的扫描需求。确保正确配置模块之间的依赖关系,以便类路径中包含所有必要的类。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值