在Spring Boot应用程序中扫描不同Maven模块/JAR的组件 [英] Scan components of different maven modules/JARs in a Spring Boot application

查看:129
本文介绍了在Spring Boot应用程序中扫描不同Maven模块/JAR的组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个Maven模块. 第一个称为应用程序",包含spring boot Application类,该类仅包含以下行:

I have two Maven modules. The first one, called "application", contains the spring boot Application class that just contains these lines:

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);
    }
}

在同一个Maven模块和软件包org.example.application中,我有一个RestController,该RestController使用一个Component,而该Component又使用了下面描述的另一个Maven模块的组件.

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.

另一个名为"model"的Maven模块包含spring boot组件(原始存储库,实体等).所有这些类都与第一个Maven模块(org.example)具有相同的包结构,但位于其子包中,例如org.example.model.entitiesorg.example.model.repositories等.

The other Maven module, called "model", contains the spring boot components (crud-repositories, entities etc). 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模块application:
SpringBootApplication -> RestController -> MyComponent

Maven module application in package org.example:
SpringBootApplication -> RestController -> MyComponent

应该在MyComponent中自动接线的组件是org.example.model软件包下的model Maven模块中的组件.

And the components that should be autowired in MyComponent are the ones in the model Maven module under the package org.example.model.

但是当我启动应用程序时,我只会得到错误:

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确实存在于Maven模块模型"中,但不能由SpringBootApplication类找到!

org.example.model.repositories.MyRepository does exist in Maven module "model" but cannot be found by the SpringBootApplication class!

如您所见,我尝试将扫描组件明确定义为: @ComponentScan({"org.example.model", "org.example"}),但这似乎无济于事.

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,而@SpringBootApplication的目标之一是(其中包括)启用组件扫描?
来自 Spring Boot文档:

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 ?
From Spring Boot documentation :

@SpringBootApplication注释等效于使用 @Configuration@EnableAutoConfiguration@ComponentScan及其 默认属性

The @SpringBootApplication annotation is equivalent to using @Configuration, @EnableAutoConfiguration and @ComponentScan with their default attributes

请注意,在Spring Boot应用程序的类上,声明@ComponentScan将值指定为basePackages时,它将覆盖@SpringBootApplication默认使用的basePackages,该默认值是该类的当前包.居住.因此,要同时具有Spring Boot Application类的包和缺少的其他包作为基本包,必须显式设置它们.

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. 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.

此外,basePackages是递归的.因此,要对位于"org.example""org.example.model"包中的类都启用扫描,请指定"org.example"就足够了,因为"org.example.model"是它的子包.

Besides basePackages is recursive. 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.

尝试:

@SpringBootApplication(scanBasePackages={"org.example"})

或者:

@SpringBootApplication
@ComponentScan("org.example")


在Spring Boot应用程序中指定@ EnableJpaRepositories/@ ComponentScan/scanBasePackages吗?

在设计Spring Boot应用程序布局时,有两种情况:


When specify @EnableJpaRepositories/@ComponentScan/scanBasePackages in a Spring Boot Application ?

As you design your Spring Boot application layout, your have two cases :

1)(倾向于)您使用的软件包布局为Spring Boot的自动配置提供了零配置.

总结:如果您的类使用Spring Bean构造型注释:@Component@Repositories@Repositories,...位于Spring Boot Application类的同一包或子包中,则仅声明 @SpringBootApplication就是您所需要的.

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.

2)(为避免这种情况),在这种情况下,您不使用将Spring Boot的自动配置提供零配置的程序包布局.

这通常意味着您需要扫描的候选类不在用@SpringBootApplication注释的类的包(或子包)中.
在这种情况下,您添加scanBasePackages属性或添加@ComponentScan以指定要扫描的程序包.
但是,此外,如果您的存储库不在您的类的包或子包中,该包或子包用@SpringBootApplication注释,则必须声明其他内容,例如:@EnableJpaRepositories(="packageWhereMyRepoAreLocated")

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.
In this case, you add the scanBasePackages attribute or add @ComponentScan to specify packages to scan.
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")

此处是有关此部分的文档(重点是我的):

80.3使用Spring数据存储库

Spring Data可以创建@Repository接口的实现 各种口味. Spring Boot会为您处理所有这些工作,只要 那些@Repositories包含在同一软件包中(或 子包).

Spring Data can create implementations of @Repository interfaces of various flavors. 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数据. 依赖于您的类路径(有一个 用于JPA的spring-boot-starter-data-jpa和一个 用于Mongodb的spring-boot-starter-data-mongodb)并创建一些 存储库接口来处理您的@Entity对象.例子在 JPA示例和Mongodb示例.

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. Examples are in the JPA sample and the Mongodb sample.

Spring Boot尝试猜测@Repository的位置 定义,基于找到的@EnableAutoConfiguration.要得到 更多控制权,请使用@EnableJpaRepositories批注(来自Spring 数据JPA).

Spring Boot tries to guess the location of your @Repository definitions, based on the @EnableAutoConfiguration it finds. To get more control, use the @EnableJpaRepositories annotation (from Spring Data JPA).


示例

1)(倾向于)您使用的软件包布局为Spring Boot的自动配置提供了零配置.


Examples

1) case (to favor) where you use a package layout that provides the auto configuration of Spring Boot with zero configuration.

使用在org.example包中声明的Spring Boot应用程序,并在同一包或org.example的子包中声明的所有bean类(包括存储库),以下声明对于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 :

package org.example;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(Application.class, args);
    }
}

存储库可以位于org.example.repository软件包中,例如:

The repositories could be located in the org.example.repository package such as :

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的自动配置提供零配置的程序包布局.

对于在org.example.application包中声明的Spring Boot应用程序,而不是在同一包或org.example.application的子包中声明的所有bean类(包括存储库),Spring Boot都需要以下声明应用程序:

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 :

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类可以如下所示.

And the bean classes could be as below.

可能来自外部JAR的存储库可以位于org.thirdparty.repository软件包中,例如:

The repositories that may come from an external a JAR could be located in the org.thirdparty.repository package such as :

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配置尽可能简单.

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应用程序中扫描不同Maven模块/JAR的组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆