我想在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;
没有 在这里工作。
请告诉我如何解决这个问题。非常感谢你。
答案 0 :(得分:1)
@Autowired
才有效。
<强> AppContextListener.java 强>
@Component // AFAIR not needed. Spring will create this bean when it will see that class implements `ApplicationListener` interface.
public class AppContextListener implements ApplicationListener<ContextRefreshedEvent> {
@Autowired
private AppContext appContext;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
appContext.initData();
}
}
<强> AppContext.java 强>
@Component
public class AppContext {
@Autowired
MyElasticsearchRepository repository;
public void initData(){
List<MyEntity> dataList = repository.findAllEntities();//repository is null here
//.......
}
}
答案 1 :(得分:1)
您的代码存在一些问题。
首先,您使用的是单一模式,我认为这是一种反模式,特别是与自动接线结合使用时。
您的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为什么现场注射是邪恶的,应该避免。
答案 2 :(得分:0)
@Autowired仅在构造AppContext对象后才起作用。由于您尝试在构造函数中访问@Autowired元素,因此它不存在。
答案 3 :(得分:0)
你不能这样做吗?
@Component
public class AppContextListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicantContext context = event.getApplicationContext();
MyElasticsearchRepository repository = context.getBean(MyElasticSearchRepository.class);
//do stuff
}
}