[英]Scan components of different maven modules/JARs in a Spring Boot application
I have two Maven modules. 我有两个Maven模块。 The first one, called "application", contains the
spring boot
Application class that just contains these lines: 第一个名为“application”,包含仅包含以下行的
spring boot
应用程序类:
package org.example.application;
@SpringBootApplication
@ComponentScan({"org.example.model", "org.example"})
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
}
}
In the same Maven module and package, org.example.application
, I have a RestController
that uses a Component
that in turn uses the components of the other Maven module described below. 在同一个Maven模块和包
org.example.application
,我有一个使用Component
的RestController
,而Component
又使用下面描述的另一个Maven模块的组件。
The other Maven module, called "model", contains the spring boot
components (crud-repositories, entities etc). 另一个名为“model”的Maven模块包含
spring boot
组件(crud-repositories,实体等)。 All those classes are under the same package structure as the first Maven module ( org.example
) but in subpackages of that, like org.example.model.entities
, org.example.model.repositories
etc. 所有这些类都与第一个Maven模块(
org.example
)在相同的包结构下,但在其子包中,如org.example.model.entities
, org.example.model.repositories
等。
So, the flow is like this: 所以,流程是这样的:
Maven module application
in package org.example : 包org.example中的 Maven模块
application
程序:
SpringBootApplication -> RestController -> MyComponent
And the components that should be autowired in MyComponent
are the ones in the model
Maven module under the package org.example.model
. 应该在
MyComponent
中自动装配的组件是包org.example.model
下的model
Maven模块中的组件。
But when I start the application I just get the error: 但是当我启动应用程序时,我只是得到错误:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field myRepository in org.example.MyComponent required a bean of type 'org.example.model.repositories.MyRepository' that could not be found.
Action:
Consider defining a bean of type 'org.example.model.repositories.MyRepository' in your configuration.
org.example.model.repositories.MyRepository
does exist in Maven module "model" but cannot be found by the SpringBootApplication class! org.example.model.repositories.MyRepository
确实存在于Maven模块“model”中,但是SpringBootApplication类找不到它!
As you can see, I have tried to explicitly define the scan components to: @ComponentScan({"org.example.model", "org.example"})
but that does not seem to help. 正如您所看到的,我尝试将扫描组件明确定义为:
@ComponentScan({"org.example.model", "org.example"})
但这似乎没有帮助。
So what have I done wrong? 那我做错了什么?
The first thing that you should wonder is : why do you declare @ComponentScan
while one of the goal of @SpringBootApplication
is (among other things) to enable the component scan ? 你应该想知道的第一件事是:为什么你声明
@ComponentScan
而@SpringBootApplication
的目标之一是(除其他事项外)启用组件扫描?
From Spring Boot documentation : 从Spring Boot文档 :
The
@SpringBootApplication
annotation is equivalent to using@Configuration
,@EnableAutoConfiguration
and@ComponentScan
with their default attributes@SpringBootApplication
注释等同于使用@Configuration
@EnableAutoConfiguration
,@ComponentScan
@EnableAutoConfiguration
和@ComponentScan
及其默认属性
Note that when on the class of your Spring Boot Application, you declare @ComponentScan
to specify a value as basePackages
, it overrides the basePackages
used by default by @SpringBootApplication
that is the current package where the class resides. 需要注意的是,当上班级的春天启动应用程序,你声明
@ComponentScan
指定值basePackages
,它将覆盖basePackages
通过默认使用@SpringBootApplication
这是类所在的当前包。 So to have as base package both the package of the Spring Boot Application class and the additional packages that were missing, you have to explicitly set them. 因此,要将Spring Boot Application类的包和缺少的其他包作为基础包,您必须明确设置它们。
Besides basePackages
is recursive. 除了
basePackages
是递归的。 So to enable the scan both for classes locating in the "org.example"
and "org.example.model"
packages, specifying "org.example"
is enough as "org.example.model"
is a sub-package of it. 因此,要为位于
"org.example"
和"org.example.model"
包中的类启用扫描,指定"org.example"
就足够了,因为"org.example.model"
是它的子包。
Try that : 试试看:
@SpringBootApplication(scanBasePackages={"org.example"})
Or alternatively : 或者:
@SpringBootApplication
@ComponentScan("org.example")
As you design your Spring Boot application layout, your have two cases : 在设计Spring Boot应用程序布局时,您有两种情况:
1) case (to favor) where you use a package layout that provides the auto configuration of Spring Boot with zero configuration. 1)case(赞成)你使用一个包布局,它提供Spring Boot的零配置自动配置。
To summarize : if your classes annotated with Spring Bean stereotypes : @Component
, @Repositories
, @Repositories
,... are located in the same package or a sub-package of the Spring Boot Application class, declaring only @SpringBootApplication
is all you need. 总结一下:如果您的类使用Spring Bean
@Component
型注释: @Component
@Repositories
, @Repositories
@Repositories
, @Repositories
,...位于Spring Boot Application类的相同包或子包中,则只需声明@SpringBootApplication
。
2) case (to avoid) where you don't use a package layout that provides the auto configuration of Spring Boot with zero configuration. 2)大小写(避免)你不使用的软件包布局提供Spring引导的零配置自动配置。
It generally means that you have candidate classes to scan that are not in the package (or sub-package) of your class annotated with @SpringBootApplication
. 它通常意味着您有要扫描的候选类,这些类不在使用
@SpringBootApplication
注释的类的包(或子包)中。
In this case, you add the scanBasePackages
attribute or add @ComponentScan
to specify packages to scan. 在这种情况下,您可以添加
scanBasePackages
属性或添加@ComponentScan
以指定要扫描的包。
But additionally, if your repositories are not located in a package or sub-package of your class annotated with @SpringBootApplication
, something else has to be declared such as : @EnableJpaRepositories(="packageWhereMyRepoAreLocated")
但另外,如果您的存储库不在使用
@SpringBootApplication
注释的类的包或子包中,则必须声明其他内容,例如: @EnableJpaRepositories(="packageWhereMyRepoAreLocated")
Here is the documentation about this part (emphasis is mine) : 这是关于这部分的文档 (重点是我的):
80.3 Use Spring Data Repositories
80.3使用Spring Data Repositories
Spring Data can create implementations of @Repository interfaces of various flavors.
Spring Data可以创建各种风格的@Repository接口的实现。 Spring Boot handles all of that for you, as long as those @Repositories are included in the same package (or a sub-package) of your @EnableAutoConfiguration class.
Spring Boot会为您处理所有这些,只要这些@Repositories包含在@EnableAutoConfiguration类的同一个包(或子包)中。
For many applications, all you need is to put the right Spring Data dependencies on your classpath (there is a spring-boot-starter-data-jpa for JPA and a spring-boot-starter-data-mongodb for Mongodb) and create some repository interfaces to handle your @Entity objects.
对于许多应用程序,您只需要在类路径上放置正确的Spring Data依赖项(对于JPA有一个spring-boot-starter-data-jpa,对于Mongodb有一个spring-boot-starter-data-mongodb)并创建一些存储库接口来处理您的@Entity对象。 Examples are in the JPA sample and the Mongodb sample.
例子在JPA样本和Mongodb样本中。
Spring Boot tries to guess the location of your @Repository definitions, based on the @EnableAutoConfiguration it finds.
Spring Boot会根据找到的@EnableAutoConfiguration尝试猜测@Repository定义的位置。 To get more control, use the @EnableJpaRepositories annotation (from Spring Data JPA).
要获得更多控制,请使用@EnableJpaRepositories批注(来自Spring Data JPA)。
1) case (to favor) where you use a package layout that provides the auto configuration of Spring Boot with zero configuration. 1)case(赞成)你使用一个包布局,它提供Spring Boot的零配置自动配置。
With a Spring Boot application declared in the org.example
package, and all bean classes (Repositories included) declared in the same package or a sub-package of org.example
, the following declaration is enough for the Spring Boot application : 使用在
org.example
包中声明的Spring Boot应用程序,以及在同一个包或org.example
的子包中声明的所有bean类(包含的存储库),以下声明对于Spring Boot应用程序来说已经足够了:
package org.example;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
}
}
The repositories could be located in the org.example.repository
package such as : 存储库可以位于
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>, { }
The controllers could be located in the org.example.controller
package : 控制器可以位于
org.example.controller
包中:
package org.example.controller;
@RestController
@RequestMapping("/api/foos")
public class FooController {...}
and so for... 等......
2) case (to avoid) where you don't use a package layout that provides the auto configuration of Spring Boot with zero configuration. 2)大小写(避免)你不使用的软件包布局提供Spring引导的零配置自动配置。
With a Spring Boot application declared in the org.example.application
package, and not all bean classes (Repositories included) declared in the same package or a sub-package of org.example.application
, the following declaration will be required for the Spring Boot application : 使用
org.example.application
包中声明的Spring Boot应用程序,而不是在同一个包或org.example.application
的子包中声明的所有bean类(包含的存储库),Spring将需要以下声明:启动应用:
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);
}
}
And the bean classes could be as below. bean类可以如下所示。
The repositories that may come from an external a JAR could be located in the org.thirdparty.repository
package such as : 可能来自外部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>, { }
The controllers could be located in the org.example.controller
package : 控制器可以位于
org.example.controller
包中:
package org.example.controller
@RestController
@RequestMapping("/api/foos")
public class FooController {...}
and so for... 等......
Conclusion : defining the Spring Boot application in the base package of your namespace is really encouraged to make the Spring Boot configuration as simple as possible. 结束语 :我们鼓励在命名空间的基础包中定义Spring Boot应用程序,以使Spring Boot配置尽可能简单。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.