我试图从控制器外部(在某些线程内部)更新表行数据,并始终获取'NullPointerException'。
线程代码:
public class S3Thread implements Runnable {
@Autowired
private IAutomationService automationService;
@Override
public void run() {
Automation config = new Automation("user1","success");
automationService.updateAutomation(config);
}
}
NullPointer异常引发以下行: automationService.updateAutomation(config);
注意:我能够从控制器类创建/更新。仅在线程中。
答案 0 :(得分:1)
好吧,这是经典的Why is my Spring @Autowired
field null
案例。您自己创建了S3Thread
实例,因此,没有注入任何bean。
考虑到您只想在单独的线程中做某事,可以考虑使用@Async
:
@Async
public void updateAutomationConfiguration() {
Automation config = new Automation("user1", "success");
automationService.updateAutomation(config);
}
注释:
@EnableAsync
批注添加到任何配置类(例如您的主类)中,以使这项工作生效。updateAutomationConfiguration()
类添加到控制器本身。直接调用同一bean中的方法会绕过代理逻辑。解决方案是将该方法放在一个单独的bean中,该bean可以在控制器内自动装配和调用。我在this answer中提供了有关替代解决方案的更详细的答案。Spring也有creating asynchronous methods的入门指南。
或者,还有一些执行asynchronous calls within controllers的方法,例如通过在控制器中使用CompletableFuture
:
@PutMapping("/automation/configuration")
public CompletableFuture<String> updateAutomationConfiguration() {
return CompletableFuture.supplyAsync(() -> {
Automation config = new Automation("user1", "success");
return automationService.updateAutomation(config);
});
}
相关:How to create a non-blocking @RestController
webservice in Spring?
答案 1 :(得分:0)
Spring不会扫描您的可运行对象,因为它未使用@Component进行注释。请尝试使用@ Component / @ Service对其进行注释。 不过不要忘记设置范围必需的范围!
答案 2 :(得分:0)
有2种可能的解决方案来解决您的问题:
您需要通过使用S3Thread
或@Service
对其进行注释,并在调用类上自动进行布线,从而使@Component
类成为服务,或者可以使用构造函数来初始化{ {1}},例如automationService
答案 3 :(得分:0)
由于您的线程类不是由spring管理的,因此您将无法在S3Thread类中注入spring托管的bean。
为此,您需要创建一个类或工厂,该类或工厂应该与春季生命周期挂钩。
拥有该类的所有权后,您可以获取适当的bean,并将引用直接传递到S3Thread类上/或在S3Thread类中使用。像这样
@Component
public class ApplicationContextUtils implements ApplicationContextAware {
private static ApplicationContext ctx;
@Override
public void setApplicationContext(ApplicationContext appContext)
{
ctx = appContext;
}
public static ApplicationContext getApplicationContext() {
return ctx;
}
}
public class S3Thread implements Runnable {
@Override
public void run() {
Automation config = new Automation("user1","success");
IAutomationService automationService=
ApplicationContextUtils.getApplicationContext().getBean(IAutomationService .class);
automationService.updateAutomation(config);
}
}