Spring Boot scanBasePackages无法从依赖项中找到bean

Posted

技术标签:

【中文标题】Spring Boot scanBasePackages无法从依赖项中找到bean【英文标题】:Spring Boot scanBasePackages unable to find beans from dependency 【发布时间】:2020-10-02 21:45:07 【问题描述】:

我有以下内容:

@SpringBootApplication(scanBasePackages = "com.my.package","com.my.package.mylibrary")
@EnableAsync
@EnableSwagger2
@ServletComponentScan
@EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class,
        HibernateJpaAutoConfiguration.class)
public class MySpringBootApplication ....

这个应用程序有包com.my.package,它还有一个包含我想在这个应用程序中自动装配的spring bean的库依赖项,这些bean在库内的包com.my.package.mylibrary中。

所以我把两者都放在scanBasePackages 上。但是 Spring 无法从库中找到 bean?

编辑:

从图书馆,我有:

package com.my.package.mylibrary.repository;
....
public interface MyRepository extends JpaRepository<..., ....> ....

在申请中,我有:

package com.my.package.controller;
....
@RestController
public class MyController ....

MySpringBootApplication 驻留在 com.my.package 中。

错误:

Exception in thread "main" java.lang.NoClassDefFoundError: com/my/package/mylibrary/repository/MyRepository
    at com.my.package.MySpringBootApplication.main(MySpringBootApplication.java:32)
Caused by: java.lang.ClassNotFoundException: com.my.package.mylibrary.repository.MyRepository
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)

我为存储库包添加了@EnableJpaRepositories。现在我看到与 MyRepository 所基于的实体 MyEntity 相关的错误。

"java.lang.TypeNotPresentException: Type com.my.package.mylibrary.domain.MyEntity not present

所以我为“com.my.package.mylibrary.domain”添加了@EntityScan,但这会使应用程序无限卡住。

【问题讨论】:

让我们在包com.my.packagecom.my.package.mylibrary中显示几个类! 请添加显示的错误信息 @SpringBootApplication 注解等效于使用 Configuration、EnableAutoConfiguration 和 ComponentScan 及其默认属性:[...]。如果没有定义特定的包,将从声明该注解的类的包开始扫描。 但是它无法检测到依赖jar中的bean。 阅读此***.com/questions/33619532/… 【参考方案1】:

首先,您不需要在@SpringBootApplication 中添加scanBasePackages 属性,因为基础包是com.my.package

如果包完全不同,那么您可以添加它。

如果基础包相同,Spring Boot 会自动拾取 bean。

在编写代码时应该遵循一种称为关注点分离的东西。


将您的 MySpringBootApplication 类更新为:

@SpringBootApplication
@ServletComponentScan
public class MySpringBootApplication ....

为异步方法执行创建一个单独的配置。

 @Configuration
 @EnableAsync
 public class AsynchronousConfig .....

为 Swagger 2 创建一个单独的配置类。

@Configuration
@EnableSwagger2
public class SwaggerConfiguration ....

创建单独的配置以排除配置。

@Configuration
@EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class, 
DataSourceTransactionManagerAutoConfiguration.class,
HibernateJpaAutoConfiguration.class)
public class ExcludeConfigurationFile ....

注意: Spring boot 自动配置会自动拾取这些@Configuration 文件

这应该可行。

【讨论】:

我已删除 ServletComponentScan。 EntityScan 和 EnableJpaRepositories。我仍然看到 java.lang.TypeNotPresentException: Type com.my.package.mylibrary.domain.MyEntity 不存在。不知何故,spring 无法加载实体类。 @Mandroid 你有这个实体 com.my.package.mylibrary.domain.MyEntity 吗? 是的。 MyRepository 是为它定义的。 @Mandroid 添加 com.my.package.mylibrary.domain.MyEntity 的代码 ? @Mandroid 检查 MyEntity 类是否存在?【参考方案2】:

您可能希望单独扫描包并将您的 JpaRepository 更改为 CrudRepository。分层配置如下。

@SpringBootApplication(scanBasePackages = "com.my.package.controller")
@EnableJpaRepositories(basePackages = "com.my.package.mylibrary.repository")
@EntityScan(basePackages = "com.my.package.mylibrary.domain")
public class MySpringBootApplication 

    public static void main(String[] args) 
        MySpringBootApplication.run(MySpringBootApplication.class, args);
    

【讨论】:

以上是关于Spring Boot scanBasePackages无法从依赖项中找到bean的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Spring Boot 应用程序 pom 同时需要 spring-boot-starter-parent 和 spring-boot-starter-web?

《02.Spring Boot连载:Spring Boot实战.Spring Boot核心原理剖析》

spring-boot-quartz, 依赖spring-boot-parent

spring-boot系列:初试spring-boot

Spring Boot:Spring Boot启动原理分析

Spring Boot:Spring Boot启动原理分析