您应该想知道的第一件事是:为什么您要声明@ComponentScan
而目标之一@SpringBootApplication
是(除其他外)启用组件扫描?
From Spring Boot 文档 http://docs.spring.io/autorepo/docs/spring-boot/current/reference/html/using-boot-using-springbootapplication-annotation.html :
The @SpringBootApplication
注解相当于使用@Configuration
, @EnableAutoConfiguration
and @ComponentScan
和他们的
默认属性
请注意,在 Spring Boot 应用程序的类上,您声明@ComponentScan
将值指定为basePackages
,它会覆盖basePackages
默认情况下使用@SpringBootApplication
这是该类所在的当前包。因此,要将 Spring Boot 应用程序类的包和缺少的附加包都作为基础包,您必须显式设置它们。
Besides basePackages
是递归的。因此,要启用扫描位于"org.example"
and "org.example.model"
包,指定"org.example"
就足够了"org.example.model"
是它的一个子包。
尝试一下:
@SpringBootApplication(scanBasePackages={"org.example"})
或者:
@SpringBootApplication
@ComponentScan("org.example")
当在 Spring Boot 应用程序中指定 @EnableJpaRepositories/@ComponentScan/scanBasePackages 时?
当您设计 Spring Boot 应用程序布局时,您有两种情况:
1) 使用包布局(以零配置提供 Spring Boot 自动配置)的情况(有利)。
总结一下:如果您的类使用 Spring Bean 构造型注释:@Component
, @Repositories
, @Repositories
,...位于 Spring Boot Application 类的同一个包或子包中,仅声明@SpringBootApplication
是你所需要的全部。
2)不使用提供 Spring Boot 零配置自动配置的包布局的情况(避免)。
这通常意味着您要扫描的候选类不在您的类的包(或子包)中注释为@SpringBootApplication
.
在这种情况下,您添加scanBasePackages
属性或添加@ComponentScan
指定要扫描的包。
但此外,如果您的存储库不位于带有注释的类的包或子包中@SpringBootApplication
,还必须声明其他内容,例如:@EnableJpaRepositories(="packageWhereMyRepoAreLocated")
这是文档 https://docs.spring.io/spring-boot/docs/current/reference/html/howto-data-access.html#howto-use-spring-data-repositories关于这部分(重点是我的):
80.3 使用 Spring 数据存储库
Spring Data 可以创建 @Repository 接口的实现
各种口味。Spring Boot 会为您处理所有这些,只要
这些@Repositories包含在同一个包中(或
@EnableAutoConfiguration 类的子包)。
对于许多应用程序,您所需要做的就是放置正确的 Spring Data
依赖于你的类路径(有一个
spring-boot-starter-data-jpa 用于 JPA 和
spring-boot-starter-data-mongodb for Mongodb)并创建一些
用于处理 @Entity 对象的存储库接口。例子在
JPA 示例和 Mongodb 示例。
Spring Boot 尝试猜测您的 @Repository 的位置
定义,基于它找到的@EnableAutoConfiguration。要得到
更多控制,使用 @EnableJpaRepositories 注释(来自 Spring
数据 JPA)。
Examples
1) 使用包布局(以零配置提供 Spring Boot 自动配置)的情况(有利)。
在 Spring Boot 应用程序中声明org.example
包,以及在同一包或子包中声明的所有 bean 类(包括存储库)org.example
,对于 Spring Boot 应用程序来说,以下声明就足够了:
package org.example;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
}
}
存储库可以位于org.example.repository
包例如:
package org.example.repository;
@Repository
public interface FooRepository extends JpaRepository<Foo, Long>, { }
and
package org.example.repository;
@Repository
public interface BarRepository extends JpaRepository<Bar, Long>, { }
控制器可以位于org.example.controller
包裹 :
package org.example.controller;
@RestController
@RequestMapping("/api/foos")
public class FooController {...}
所以对于...
2)不使用提供 Spring Boot 零配置自动配置的包布局的情况(避免)。
在 Spring Boot 应用程序中声明org.example.application
包,而不是在同一个包或子包中声明的所有 bean 类(包括存储库)org.example.application
,Spring Boot应用程序需要以下声明:
package org.example.application;
@SpringBootApplication(scanBasePackages= {
"org.example",
"org.thirdparty.repository"})
@EnableJpaRepositories("org.thirdparty.repository")
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
}
}
Bean 类可能如下所示。
可能来自外部 JAR 的存储库可能位于org.thirdparty.repository
包例如:
package org.thirdparty.repository;
@Repository
public interface FooRepository extends JpaRepository<Foo, Long>, { }
and
package org.thirdparty.repository;
@Repository
public interface BarRepository extends JpaRepository<Bar, Long>, { }
控制器可以位于org.example.controller
包裹 :
package org.example.controller
@RestController
@RequestMapping("/api/foos")
public class FooController {...}
所以对于...
结论:确实鼓励在命名空间的基础包中定义 Spring Boot 应用程序,以使 Spring Boot 配置尽可能简单。