SpringBoot:无法从其他JAR库自动装配类

20

我正在开发一个SpringBoot应用程序(例如MyApp),它依赖于两个具有不同实现的数据项目:

data-jdbc.jar

  • 使用spring-boot-starter-jdbc构建,它公开了JDBCDataService类,该类将被我的应用程序使用

示例代码:

@Service 
public class JDBCDataServiceImpl implements JDBCDataService {

@Autowired
private JDBCDataRepository jdbcDataRepository;    
... 
}
  • 使用my.data.jdbc
  • 没有SpringBoot主类。Spring配置仅为单元测试类创建
  • 存储库类正在使用JDBCTemplate

示例存储库:

@Repository
public class JDBCDataRepositoryImpl implements JDBCDataRepository {

@Autowired
protected JdbcTemplate jdbcTemplate;
...
}

data-jpa.jar

  • 使用spring-boot-starter-data-jpa构建,该工具还提供了JPADataService类,我的应用程序也将使用它

示例代码:

@Service 
public class JPADataServiceImpl implements JPADataService {

@Autowired
private JPADataRepository jpaDataRepository;    
... 
}
  • 使用my.data.jpa
  • 没有SpringBoot主类。Spring配置仅为单元测试类创建
  • 存储库类扩展了CrudRepository接口

示例存储库:

@Repository
public interface JPADataRepository extends CrudRepository<MyObject, Integer{
...
}

在我的SpringBoot项目中,我有以下的SpringBoot主应用程序:
@SpringBootApplication
public class MyApp extends SpringBootServletInitializer {
}

在我的业务服务MainService类中,我有以下的注入。
@Service
public class MainServiceImpl implements MainService {

@Autowired
private JDBCDataService jdbcDataService;

@Autowired
private JPADataService jpaDataService;

然而,我遇到了问题“Could not Autowire. No beans of 'JPADataService' type found”,该问题仅存在于JPADataService类中,但对于JDBCService类却可以正常工作。
我尝试了以下问题中提到的解决方案,但在我的情况下都不起作用: 无法为存在于依赖库jar中的Bean使用@Autowire吗?
@ComponentScan(basePackages = {"org.example.main", "package.of.user.class"})

如何自动装配一个来自外部jar包的Spring bean?

@Configuration
@ComponentScan("com.package.where.my.class.is")
class Config {
...
}

我已经找到了解决方案。为了扫描我的数据库库,我必须将主要的MyApp.java文件上移一个包级别。

我不再将MyApp.java放在my.app包下,而是必须将其移到my下,以便成功扫描带有my.data.jpamy.data.jdbc包的库。


只有在 JPADataService 类上标注了 @Component 才能使用 @ComponentScan。您需要在 @Configuration 类中添加一个带有 @Bean 注释的方法。http://docs.spring.io/spring-javaconfig/docs/1.0.0.m3/reference/html/creating-bean-definitions.html - Christopher Schneider
@Christopher Schneider,两个JAR文件中的服务类都实际上使用了@Service注解。据我所知,@ComponentScan也应该能够读取这些类。 - Jown
@Service 应该处理它。你说你没有主类,那么应用程序的入口在哪里? - Christopher Schneider
入口点在我正在开发的新SpringBoot应用程序(MyApp)中,因此我将这些数据作为我的maven项目依赖项。 - Jown
4个回答

16

我现在已经找到了解决方案。为了扫描我的数据库,我必须将主要的MyApp.java向上移动一个包级别。

不是将我的MyApp.java放在my.app包下面,而是必须将它放在my下面,以成功扫描带有my.data.jpamy.data.jdbc包的库。


为什么会发生这种情况?这是一个 bug 还是 Spring Boot 的特性? - ajaristi
2
这不是一个 bug,@ComponentScan 默认会从定义主类的包及其子目录中扫描。 - Gagandeep Kalra
1
你是一个救命恩人@Jown。我花了将近一天的时间来解决我的应用程序中的问题。我在我的SpringBoot主应用程序调用中添加了ComponentScan,它解决了实际问题,但这导致了我的应用程序内部出现了其他问题。我移动了SpringBoot主类,这解决了我的问题。真的非常感谢你,你拯救了我的周末...太棒了! - Satya P

12

@ComponentScan 增加并不起作用,如果您尝试自动装配的类没有使用 @Component 进行注释。为了让这个工作,您必须在您的 @Configuration 类中注释一个方法。像这样的东西应该允许您自动装配类:

@Configuration
public class ConfigClass{

    @Bean
    public JPADataService jpaDataService(){
        return new JPADataService();
    }
}

我应该补充一下,我不熟悉JPADataService。它可能需要某种我没有考虑到的配置。 - Christopher Schneider
如果是这种情况,那么在使用JDBCService对象时也不应该起作用,因为我没有在应用程序中的任何Java配置文件中声明这个类。据我所知,只需要使用@SpringBootApplication就可以让它自动运行 :-) - Jown
有人知道为什么 '@ComponentScan' 不起作用吗?我遇到了同样的问题,我的存储库甚至带有 '@Repository' 注释,并添加了一个 ComponentScan,其中基本包值是上一级,Spring 可以从 jar 库中看到所有 bean。只有当我像 @Jown 说的那样将 SpringBootApplication 上移一级时,应用程序才能正常工作。 - SHAKU

2

您需要在外部jar包中配置spring.factories

external-jar-project
   |--java
   |--resources
        |-- META-INF
              |-- spring.factories

spring.factories的内容如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=xxx

-6
这个问题也困扰了我很长时间。我发现的是,Spring Boot 不能扫描你引入的 jar 包路径下的相关类。
你可能需要使用像 @EnableJpaRepositories("cn.XXX") @EntityScan("cn.XXX") 这样的注解来扫描你的类。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接