java – 在Spring Boot应用程序中扫描不同maven模块/ JAR的组件

前端之家收集整理的这篇文章主要介绍了java – 在Spring Boot应用程序中扫描不同maven模块/ JAR的组件前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有两个Maven模块.
第一个名为“application”,包含仅包含以下行的 Spring引导应用程序类:
  1. package org.example.application;
  2.  
  3. @SpringBootApplication
  4. @ComponentScan({"org.example.model","org.example"})
  5. public class Application {
  6. public static void main(String[] args) {
  7. ApplicationContext ctx = SpringApplication.run(Application.class,args);
  8. }
  9. }

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

另一个名为“model”的Maven模块包含spring引导组件(crud-repositories,实体等).所有这些类都与第一个Maven模块(org.example)在相同的包结构下,但在其子包中,如org.example.model.entities,org.example.model.repositories等.

所以,流程是这样的:

包org.example中的Maven模块应用程序:
SpringBootApplication – > RestController – >为MyComponent

应该在MyComponent中自动装配的组件是包org.example.model下的模型Maven模块中的组件.

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

  1. ***************************
  2. APPLICATION Failed TO START
  3. ***************************
  4.  
  5. Description:
  6.  
  7. Field myRepository in org.example.MyComponent required a bean of type 'org.example.model.repositories.MyRepository' that could not be found.
  8.  
  9. Action:
  10.  
  11. Consider defining a bean of type 'org.example.model.repositories.MyRepository' in your configuration.

org.example.model.repositories.MyRepository确实存在于Maven模块“model”中,但是SpringBootApplication类找不到它!

如您所见,我尝试将扫描组件明确定义为:
@ComponentScan({“org.example.model”,“org.example”})但这似乎没有帮助.

那我做错了什么?

解决方法

你应该想知道的第一件事是:为什么你声明@ComponentScan而@SpringBootApplication的目标之一是(除其他事项外)启用组件扫描?
Spring Boot documentation开始:

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

请注意,在Spring Boot Application的类上,声明@ComponentScan将值指定为basePackages,它会覆盖默认情况下由@SpringBootApplication使用的basePackages,它是类所在的当前包.因此,要将Spring Boot Application类的包和缺少的其他包作为基础包,您必须明确设置它们.

除了basePackages是递归的.因此,要为位于“org.example”和“org.example.model”包中的类启用扫描,指定“org.example”就足够了,因为“org.example.model”是它的子包.

试试看:

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

或者:

  1. @SpringBootApplication
  2. @ComponentScan("org.example")

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

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

1)case(赞成)你使用一个包布局,它提供Spring Boot的零配置自动配置.

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

2)大小写(避免)你不使用的软件包布局提供Spring引导的零配置自动配置.

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

关于这部分的Here is the documentation(重点是我的):

80.3 Use Spring Data 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.

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 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)case(赞成)你使用一个包布局,它提供Spring Boot的零配置自动配置.

使用在org.example包中声明的Spring Boot应用程序,以及在同一个包或org.example的子包中声明的所有bean类(包含的存储库),以下声明对于Spring Boot应用程序来说已经足够了:

  1. package org.example;
  2.  
  3. @SpringBootApplication
  4. public class Application {
  5. public static void main(String[] args) {
  6. ApplicationContext ctx = SpringApplication.run(Application.class,args);
  7. }
  8. }

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

  1. package org.example.repository;
  2.  
  3. @Repository
  4. public interface FooRepository extends JpaRepository<Foo,Long>,{ }

  1. package org.example.repository;
  2.  
  3. @Repository
  4. public interface BarRepository extends JpaRepository<Bar,{ }

控制器可以位于org.example.controller包中:

  1. package org.example.controller;
  2.  
  3. @RestController
  4. @RequestMapping("/api/foos")
  5. public class FooController {...}

等……

2)大小写(避免)你不使用的软件包布局提供Spring引导的零配置自动配置.

使用org.example.application包中声明的Spring Boot应用程序,而不是在同一个包或org.example.application的子包中声明的所有bean类(包含的存储库),Spring将需要以下声明:启动应用:

  1. package org.example.application;
  2.  
  3. @SpringBootApplication(scanBasePackages= {
  4. "org.example","org.thirdparty.repository"})
  5. @EnableJpaRepositories("org.thirdparty.repository")
  6. public class Application {
  7. public static void main(String[] args) {
  8. ApplicationContext ctx = SpringApplication.run(Application.class,args);
  9. }
  10. }

bean类可以如下所示.

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

  1. package org.thirdparty.repository;
  2.  
  3. @Repository
  4. public interface FooRepository extends JpaRepository<Foo,{ }

  1. package org.thirdparty.repository;
  2.  
  3. @Repository
  4. public interface BarRepository extends JpaRepository<Bar,{ }

控制器可以位于org.example.controller包中:

  1. package org.example.controller
  2.  
  3. @RestController
  4. @RequestMapping("/api/foos")
  5. public class FooController {...}

等……

结束语:我们鼓励在命名空间的基础包中定义Spring Boot应用程序,以使Spring Boot配置尽可能简单.

猜你在找的Java相关文章