java - 如何在ApplicationListener中初始化 Autowiring 对象?

标签 java spring javabeans

我想读取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/

相关文章:

java - 用 Java 流式传输音频/广播?

java - 从 ClientErrorException 获取状态

java - 在 Hibernate 中使用 javax.management.* api

java - Hibernate 禁用默认行为

java - JSF SelectOneMenu 获取实体

java - jsp:setProperty 相当于 servlet

java - Map.get(Object key) 不是(完全)通用的原因是什么

java - 在多核 CPU 上运行的多个 JVM 会互相阻塞吗?

spring - 在Spring Security中的@PreFilter和@PostFilter中获取Collection/Array对象的句柄

java - Apache CXF + Spring : Generating a Simple Client