Spring对于Java开发者来说,熟悉程度大概与word、excel这些office软件相当。这是个人猜测,大家也可以来投个票:
它简单易用,极大降低了开发人员的门槛。但是,它毕竟是建立在很多约定俗成的规则之上。而这些约定并不一定是你所熟悉的。所以,当你遇到问题时,很有可能就抓狂了。
前段时间我做了网络编程的系列课程,过年了,咱们换换脑子。争取不太烧脑的情况下,来一个spring避坑指南的系列课程。
问题
在使用 @Autowired 时,不管你是菜鸟级还是专家级的 Spring 使用者,都应该制造或者遭遇过类似的错误:
required a bean of type 'xxx' that could not be found在构建 Web 服务时,我们常使用 Spring Boot 来快速构建。
例如,使用下面的包结构和相关代码来完成一个简易的 Web 版 HelloWorld:其中,负责启动程序的 Application 类定义如下:
@SpringBootApplication public class Application { public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); } }
提供接口的 HelloWorldController 代码如下:
@RestController public class HelloWorldController { @GetMapping(path = "hi") public String hi() { return "新年快乐!"; } }
不出意外,访问时结果应该如下所示:
其中 HelloWorldController 因为添加了 @RestController,最终被识别成一个 Controller 的 Bean。
但是,假设有一天,我们希望用更清晰的包层次和结构来管理时,可能将Application 移动到一个单独的目录下,比如下面这样:
这时候访问就404了:
实际上,我们没有改变任何代码,只是改变了包的结构,但是我们会发现这个 Web 应用失效了,即不能识别出 HelloWorldController 了。也就是说,我们找不到 HelloWorldController 这个 Bean 了。这是为何?
解析
要了解 HelloWorldController 为什么会失效,就需要先了解之前是如何生效的。对于 Spring Boot 而言,关键点在于 Application.java 中使用了 SpringBootApplication 注解。而这个注解继承了另外一些注解,具体定义如下:
@EnableAutoConfiguration @ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} ) public @interface SpringBootApplication {
从定义可以看出,SpringBootApplication 开启了很多功能,其中一个关键功能就是 ComponentScan。当 Spring Boot 启动时,ComponentScan 的启用意味着会去扫描出所有定义的 Bean,那么扫描什么位置呢?这是由 ComponentScan 注解的 basePackages 属性指定的。
直接使用的是 SpringBootApplication 注解定义的 ComponentScan,它的 basePackages 没有指定,所以默认为空(即{})。此时扫描的是什么包?
当 basePackages 为空时,扫描的包会是 declaringClass 所在的包,在本案例中,declaringClass 就是 Application,所以扫描的包其实就是它所在的包。因为后来移动目录后 Application 所在的包为 com.brmayi.concise.startup ,没有包含 HelloWorldController 所在的 com.brmayi.concise 。就扫描不到了。
这就是为什么一般咱们都会把 Application 放到项目最外层目录。这样,它所在的目录以及子目录都可以扫描到。
另外,我们也可以使用 @ComponentScans 来修复问题。
福利时间
有朋友让我拉群发红包。问题是:拉了群我说点啥呢。12月份的时候,我一看今年用户量增长很少,发力写了几篇文章。同时,也得到了贵人相助,用户增长终于完成了“KPI”。虽然我不知道贵人具体是谁,但是肯定和咱们用户朋友有很大的关系。答谢是应该的。
要做就做大的,我拉群,大家帮忙拉人进去,争取拉满500人。聊天你们聊,我只管过年发红包。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)