@Autowired 不起作用,我们不知道原因。服务和控制器位于不同的模块和包中,但我们认为这并不重要。我们可以手动实例化服务,这样控制器模块就能够“看到”公共模块。
运行该应用程序会导致以下错误:
Parameter 0 of constructor in com.xx.campaign_api.controller.MyController required a bean of type 'com.xx.campaign.common.service.MyService' that could not be found.
我们有一个多模块 spring boot 3.4.2 项目,其 pom 如下:
<project xxx
<groupId>org.springframework</groupId>
<artifactId>our-service</artifactId>
<version>0.1.0</version>
<packaging>pom</packaging>
<modules>
<module>campaign-common</module>
<module>campaign-api</module>
<module>campaign-schedule</module>
</modules>
</project>
在 api 模块中我们有一个像这样的休息控制器:
package com.xx.campaign_api.controller;
import com.xx.campaign.common.service.MyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
private MyService testService;
@Autowired
public MyController(MyService testService) { // THIS LINE IS FAILING
this.testService = testService;
}
@GetMapping("/test")
public String test() {
return testService.test();
}
}
该服务如下所示:
package com.xxx.campaign.common.service;
import org.springframework.stereotype.Service;
@Service
public class MyServiceImpl implements MyService {
@Override
public String test() {
return "test3";
}
}
package com.xxx.campaign.common.service;
public interface MyService {
public String test();
}
主要类如下所示:
package com.xx.campaign_api;
@SpringBootApplication
public class CampaignApiApplication {
public static void main(String[] args) {
SpringApplication.run(CampaignApiApplication.class, args);
}
}
在控制器模块的 pom 中,我们有:
<dependency>
<groupId>xx</groupId>
<artifactId>campaign-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
我也尝试过这个:
package com.xx.campaign_api.controller
@SpringBootApplication(scanBasePackages = "com.xx")
@RestController
public class GaController {
private MyService myService;
@Autowired
public GaController(MyService myService) { // THIS LINE IS FAILING
this.myService = myService;
}
但该应用程序无法启动并出现以下错误:
Web application could not be started as there was no org.springframework.boot.web.servlet.server.ServletWebServerFactory bean defined in the context.
问题是您的通用服务和 API 有不同的包,并且实际上并不共享一个公共的超级包(它们以 的形式共享
com.xx
)。接下来,不要
@SpringBootApplication
在代码中放置多个注释,这只会导致错误。因此,请@SpringBootApplication
从类中删除@RestController
。你可以做 3 件事来解决这个问题。
@SpringBootApplication
类)移入并从那里启动它。main
com.xx
scanBasePackages
到您的@SpringBootApplication
,虽然这对于检测组件有用,但是如果您在其中拥有实体等东西,它将不会考虑这些。@SpringBootApplication
移至顶级共享包。移动
@SpringBootApplication
注释类虽然这可能会起作用,但您可能会面临扫描过多的风险,这取决于名称
xx
。添加
scanBasePackages
到@SpringBootApplication
注释虽然这可以用于检测服务、存储库等组件。但如果这些包中有实体或 Spring Data 存储库之类的东西,则无法正常工作。要使其工作,您必须添加其他注释,如
@EntityScan
和@EnableJpaRepositories
(或您使用的任何持久性技术)。添加所有这些注释很麻烦,并且可能会导致意外,因为自动配置的一部分不再是自动配置。重组软件包并移动
@SpringBootApplication
类别。现在我建议这样做并将您的
com.xx.campaign_api
包重命名为com.xx.campaign.api
。这将使其成为的子包com.xx.campaign
。现在,当将放入CampaignApiApplication
包中时,com.xx.campaign
它将自动检测包中的所有内容com.xx.campaign
及其所有子包。无需添加任何额外的注释。最后一个也是 Spring Boot 开发人员推荐的,并在 Spring Boot 参考指南中提到。
Geba 提供的解决方案如下:
现在一切正常!