我想在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>
{ }
问题
正如您在我的代码中看到的那样,在InitData()处,存储库为null。我不
知道为什么
@Autowired MyElasticsearchRepository repository;
不在这里工作。
请告诉我如何解决此问题。非常感谢你。
最佳答案
您的代码有几处错误。
首先,您使用的是单例模式,我想说这是一种反模式,尤其是与自动布线结合使用时。
其次,在您的getInstance()
方法中,您自己创建了AppContext
的新实例。这个实例不是由Spring管理的,因此@Autowired
在这里几乎没有用,Spring只能将依赖项注入它所知道的bean中。
而是将您的AppContext
设为组件(或根据需要提供服务)。删除getInstance
方法,改用构造函数注入。
@Component
public class AppContext {
private final MyElasticsearchRepository repository;
@Autowired
public AppContext(MyElasticsearchRepository repository){
this.repository=repository;
}
...
}
第三,您尝试使用构造函数中的
@Autowired
实例(您正在进行方法调用,希望它在那里),但是只能在bean的实例上进行自动接线。因此,此时尚未进行自动接线,您的变量将始终为null
。不用从构造函数调用方法,而是使用构造函数注入或用InitData
注释@PostConstruct
方法。@PostConstruct
private void InitData(){
List<MyEntity> dataList = repository.findAllEntities();
...
}
现在,您的
AppContext
是组件,它将在春季被检测到,您只需将其注入到您的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
}
}
注意:我更喜欢将构造函数注入用于必填字段,将setter注入用于可选字段。您应避免字段注入(即实例字段上的
@Autowired
),因为这被认为是不好的做法。参见here为什么电场注入是有害的,应该避免。