第一个名为“application”,包含仅包含以下行的 Spring引导应用程序类:
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中,我有一个使用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模块中的组件.
但是当我启动应用程序时,我只是得到错误:
*************************** 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模块“model”中,但是SpringBootApplication类找不到它!
如您所见,我尝试将扫描组件明确定义为:
@ComponentScan({“org.example.model”,“org.example”})但这似乎没有帮助.
那我做错了什么?
解决方法
从 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”是它的子包.
试试看:
@SpringBootApplication(scanBasePackages={"org.example"})
或者:
@SpringBootApplication @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应用程序来说已经足够了:
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,{ }
控制器可以位于org.example.controller包中:
package org.example.controller; @RestController @RequestMapping("/api/foos") public class FooController {...}
等……
2)大小写(避免)你不使用的软件包布局提供Spring引导的零配置自动配置.
使用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); } }
bean类可以如下所示.
可能来自外部JAR的存储库可以位于org.thirdparty.repository包中,例如:
package org.thirdparty.repository; @Repository public interface FooRepository extends JpaRepository<Foo,{ }
和
package org.thirdparty.repository; @Repository public interface BarRepository extends JpaRepository<Bar,{ }
控制器可以位于org.example.controller包中:
package org.example.controller @RestController @RequestMapping("/api/foos") public class FooController {...}
等……
结束语:我们鼓励在命名空间的基础包中定义Spring Boot应用程序,以使Spring Boot配置尽可能简单.