我想读取ApplicationListener中的数据,但我的对象未初始化。下面是我的代码:
AppContextListener.java
@Component
public class AppContextListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
AppContext.getInstance();
}
}
AppContext.java
public class AppContext {
private static AppContext instance;
@Autowired
MyElasticsearchRepository repository;
public AppContext(){
InitData();
}
public static synchronized AppContext getInstance() {
if (instance == null) {
instance = new AppContext();
}
return instance;
}
private void InitData(){
List<MyEntity> dataList = repository.findAllEntities();//repository is null here
//.......
}
}
MyElasticsearchRepository.java
public interface MyElasticsearchRepository extends ElasticsearchRepository<MyEntity,String>
{ }
问题
As you can see in my code, at InitData(), repository is null. I don't know why
@Autowired MyElasticsearchRepository repository;
does not worked here.
请告诉我如何解决这个问题。非常感谢。
最佳答案
您的代码有一些问题。
首先,您使用的是单例模式,我认为这是一种反模式,尤其是与自动接线结合使用时。
第二个在 getInstance()
方法中,您自己创建一个 AppContext
的新实例。这个实例不是由 Spring 管理的,所以 @Autowired 在这里几乎没有用处,Spring 只能将依赖项注入(inject)到它知道的 bean 中。
相反,让您的 AppContext
成为一个组件(或您喜欢的服务)。删除 getInstance
方法并使用构造函数注入(inject)。
@Component
public class AppContext {
private final MyElasticsearchRepository repository;
@Autowired
public AppContext(MyElasticsearchRepository repository){
this.repository=repository;
}
...
}
第三,您尝试使用构造函数中的 @Autowired
实例(您正在执行期望它在那里的方法调用),但是 Autowiring 只能在 bean 实例上完成。因此,此时自动连接尚未发生,您的变量将始终为 null
。也不要从构造函数调用该方法,而是使用构造函数注入(inject)或使用 @PostConstruct
注释 InitData
方法。
@PostConstruct
private void InitData(){
List<MyEntity> dataList = repository.findAllEntities();
...
}
现在您的 AppContext
是一个将被 spring 检测到的组件,您只需将其注入(inject)到您的 ApplicationListener
中即可。
@Component
public class AppContextListener implements ApplicationListener<ContextRefreshedEvent> {
private final AppContext appContext;
@Autowired
public AppContextListener(AppContext appContext) {
this.appContext=appContext;
}
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
// Do your thing with appContext
}
}
注意:我更喜欢对必填字段进行构造函数注入(inject),对可选字段进行 setter 注入(inject)。您应该避免字段注入(inject)(即实例字段上的@Autowired
),因为这被认为是一种不好的做法。请参阅here为什么现场注入(inject)是邪恶的并且应该避免。
关于java - 如何在ApplicationListener中初始化 Autowiring 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30454643/