您应该想知道的第一件事是:为什么声明而目标之一是(除其他外)启用组件扫描?
从弹簧启动文档:@ComponentScan
@SpringBootApplication
该批注等效于使用 ,并具有 其默认属性@SpringBootApplication
@Configuration
@EnableAutoConfiguration
@ComponentScan
请注意,在 Spring Boot 应用程序的类上,您声明将值指定为 ,它将覆盖默认情况下使用的该类所在的当前包。因此,要将 Spring Boot Application 类的包和缺少的其他包作为基础包,必须显式设置它们。@ComponentScan
basePackages
basePackages
@SpringBootApplication
此外是递归的。因此,要对位于 和 包中的类启用扫描,指定和它的子包一样就足够了。basePackages
"org.example"
"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刻板印象注释:,,,...位于 Spring Boot Application 类的同一包或子包中,声明仅是您所需要的全部。@Component
@Repositories
@Repositories
@SpringBootApplication
2)情况(要避免)您没有使用提供Spring Boot自动配置的软件包布局,而零配置。
这通常意味着您要扫描的候选类不在用 注释的类的包(或子包)中。
在这种情况下,您可以添加属性或 add 来指定要扫描的包。
但是,此外,如果您的存储库不位于带有 注释的类的包或子包中,则必须声明其他内容,例如:@SpringBootApplication
scanBasePackages
@ComponentScan
@SpringBootApplication
@EnableJpaRepositories(="packageWhereMyRepoAreLocated")
以下是关于这部分的文档(重点是我的):
80.3 使用 Spring 数据存储库
Spring Data可以创建各种风格的@Repository接口的实现。Spring Boot会为您处理所有这些问题,只要这些@Repositories包含在@EnableAutoConfiguration类的同一包(或子包)中即可。
对于许多应用程序,您只需要将正确的Spring Data依赖项放在类路径上(JPA有一个spring-boot-starter-data-jpa和一个用于Mongodb的spring-boot-starter-data-mongodb),并创建一些存储库接口来处理@Entity对象。示例在 JPA 示例和 Mongodb 示例中。
Spring Boot 会尝试根据找到的@EnableAutoConfiguration来猜测@Repository定义的位置。要获得更多控制,请使用@EnableJpaRepositories注释(来自Spring Data JPA)。
例子
1)情况(偏爱)您使用提供零配置的Spring Boot自动配置的软件包布局。
在软件包中声明一个 Spring Boot 应用程序,并且在同一个软件包或 子软件包中声明所有 Bean 类(包括存储库),以下声明对于 Spring Boot 应用程序来说就足够了:org.example
org.example
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>, { }
和
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 应用程序,并且并非所有 Bean 类(包括存储库)都声明在同一软件包或 子软件包中,则 Spring Boot 应用程序将需要以下声明:org.example.application
org.example.application
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);
}
}
豆类可以如下所示。
可能来自外部 JAR 的存储库可以位于包中,例如:org.thirdparty.repository
package org.thirdparty.repository;
@Repository
public interface FooRepository extends JpaRepository<Foo, Long>, { }
和
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配置尽可能简单。