本文已收录在Github,关注我,紧跟本系列专栏文章,咱们下篇再续!
- 🚀 魔都架构师 | 全网30W技术追随者
- 🔧 大厂分布式系统/数据中台实战专家
- 🏆 主导交易系统百万级流量调优 & 车联网平台架构
- 🧠 AIGC应用开发先行者 | 区块链落地实践者
- 🌍 以技术驱动创新,我们的征途是改变世界!
- 👉 实战干货:编程严选网
0 前言
SpringBoot约定大于配置,但不熟悉所有约定,所以经常写bug!
1 案例:扫描不到Bean定义
Spring Boot服务包结构:

BestPractiseApplication:
java
package com.javaedge.spring.aop;
/**
* @author JavaEdge
*/
@SpringBootApplication
public class BestPractiseApplication {
public static void main(String[] args) {
SpringApplication.run(BestPractiseApplication.class, args);
}
}
MyController:
java
package com.javaedge.spring.app;
/**
* @author JavaEdge
*/
@RestController
public class MyController {
@GetMapping("hello")
public String hello() {
return "hello Java";
}
}
访问http://localhost:12345/hello
:

紧急需求,需添加多个Controller,常规操作调整包结构:

发现应用不识别MyController,找不到 MyController 这 Bean,why?

2 解惑
2.1 之前为啥生效?
@SpringBootApplication继承了其它注解:
java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
SpringBootApplication默认开启ComponentScan。SpringBoot应用启动时,ComponentScan扫描所有定义的 Bean,扫描位置由 ComponentScan 的 basePackages 属性指定:
java
package org.springframework.context.annotation;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
@AliasFor("basePackages")
String[] value() default {};
@AliasFor("value")
String[] basePackages() default {};
但basePackages默认空,那它扫描的啥包?debug 到 ComponentScanAnnotationParser#parse:

即declaringClass所在包,即com.javaedge.app
。
3 修正
如下两种方案:
3.1 放好位置


3.2 显式配置
@ComponentScan
java
package com.javaedge.spring.app;
@SpringBootApplication()
@ComponentScan("com.javaedge.spring.controller")
public class BestPractiseApplication {
public static void main(String[] args) {
SpringApplication.run(BestPractiseApplication.class, args);
}
}

@ComponentScans
java
package com.javaedge.spring.app;
@SpringBootApplication()
@ComponentScans(value = {@ComponentScan(value = "com.javaedge.spring.controller")})
public class BestPractiseApplication {
public static void main(String[] args) {
SpringApplication.run(BestPractiseApplication.class, args);
}
}
ComponentScans 相比 ComponentScan,可指定扫描多个包范围。
本文由博客一文多发平台 OpenWrite 发布!