Springboot版本是2.6.13。
我有一个类数据,它看起来像这样:
package com.example.asynctest;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
@lombok.Data
@Async
public class Data {
public class MyData{
int age;
String name = "";
}
private MyData myData = new MyData();
}
字符串
当我尝试让它自动连接时,myData
字段为空。
package com.example.asynctest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
@Slf4j
@Async
class CmmandLine implements CommandLineRunner{
@Autowired
private Data data;
@Override
public void run(String... args) throws Exception {
log.info(data.toString());
}
}
型
在IDEA中,data
字段如下所示:debug picture
当我删除@Async注解时,自动连接的data.myData
是正确的。我自己跟踪了这一点,bean被AsyncAnnotationBeanPostProcessor
的postProcessAfterInitialization
修改。我在entrypoint类上添加了@EnableAsync
。
那么,为什么会发生这种情况呢?我应该如何同时使用@Async和@Autowired呢?
1条答案
按热度按时间nue99wik1#
你的代码的问题不是
data
对象没有被注入。事实上,它确实被注入了。为了绝对确定,你可以修改你的代码以通过构造函数注入:字符串
如果
data
对象没有被正确注入,你会得到一个异常Parameter 0 of constructor in industries.atende. Tester required a bean of type 'com.example.asynctest.Data' that could not be found.
。此外,即使(理论上)你没有得到这个异常,data.toString()
也会产生一个NullPointerException
。注意,这两个异常都没有发生。所以代码(几乎)正确工作。你在错误的地方寻找错误。真实的问题是
Data
类中的toString()
方法返回null
。对象本身是notnull,但在IDEA调试中它似乎是null,因为Intellij Idea也使用方法toString()
来为您描绘对象。而IDEA从toString()
方法中获得null
。那么为什么
toString()
返回null呢?因为你把它变成了@Async
。每个@Async
方法都应该返回由一个能够处理异步响应的类 Package 的值。例如,如果方法是@Async
,你应该总是返回CompletableFuture<String>
,而不仅仅是String
。为什么?因为方法是在另一个线程上运行的,如果没有这个 Package 器,你就没有办法阻止它来获得结果(换句话说:你没有办法“等待”结果)。所以我的建议是从顶层(类型)中删除
@Async
注解,只在你真正需要的方法上使用它。因为否则你没有办法解决这个问题。toString()
是从Object
类继承的,所以它不能返回CompletableFuture<String>
-它必须返回String
。所以让方法为String
,你总是会得到null而不是真实的值。