无法捕获和处理 java 中的 spring 个自定义事件

Unable to catch and handle spring custom events in java

我正在尝试设置自定义 spring 事件发布者和侦听器。 该过程的流程似乎运行良好,我可以在事件发布之前看到打印件,但是,我的事件侦听器没有捕捉到该事件。 我的主要 class 是:

public class TestClass {

        public static void main(String[] args) throws Exception {
            testEvents();
        }

        private static void testEvents() throws InterruptedException {
            AnnotationConfigApplicationContext eventPublisherContext = new AnnotationConfigApplicationContext(EventListenerConfig.class);
            CustomSpringEventPublisher eventPublisher = eventPublisherContext.getBean(CustomSpringEventPublisher.class);
            List<CustomSpringEventListener> listenersList = new ArrayList<CustomSpringEventListener>();

            for (int i = 0; i < 5; i++) {
                listenersList.add(new CustomSpringEventListener("LR" + (i + 1)));
            }

            for (int i = 0; i < 10; i++) {
                Thread.sleep(5000);

                LocalDateTime now  = LocalDateTime.now();
                eventPublisher.doStuffAndPublishAnEvent("new event " + now.format(Formats.isolong));
            }
        }
    }

这是我的自定义事件 class:

public class CustomSpringEvent extends ApplicationEvent {
    private String message;

    public CustomSpringEvent(Object source, String message) {
        super(source);
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

}

这是我的自定义事件发布者 class:

@Component
public class CustomSpringEventPublisher {

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    public void doStuffAndPublishAnEvent(final String message) {
        System.out.println("Publishing custom event --> " + message);
        this.applicationEventPublisher.publishEvent(new CustomSpringEvent(this, message));
    }

}

这是我的自定义事件侦听器 class:

public class CustomSpringEventListener implements ApplicationListener<CustomSpringEvent> {
    private String name;

    public CustomSpringEventListener(String name) {
        this.name = name;
    }

    @Override
    @EventListener
    public void onApplicationEvent(CustomSpringEvent event) {
        System.out.println(name + " received spring custom event - " + event.getMessage());
    }

}

这是我的事件侦听器配置 class:

@Configuration
@ComponentScan({"some.local.directory.testCases"})
public class EventListenerConfig {
}

我在这里错过了什么?我怎样才能让我的监听器 class 识别发布的事件并处理它? 我看到一些示例,其中侦听器 class 具有 @Component,但是当我尝试添加它时,我从 spring 收到错误消息: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate.,我也看不出为什么在这种情况下监听器 class 会有这个注释。 任何帮助,将不胜感激。谢谢。

为了调用事件侦听器,Spring 需要知道侦听器 class 并将其放入其 applicationContext 中,在所谓的 Bean[ 下=71=].

您确实需要用 @Component 注释您的 class。但是当你这样做时,你会得到一个错误。让我们澄清一下。

快速概览Spring

@Component 注释的 class 将向 Spring 表明它需要 "manage" class 自己。通过管理,它包括先创建所有"dependencies",然后调用"constructor"。我们称其为 依赖树 。一旦 Spring 到达底部,它就可以开始向上爬并创建对象并返回顶部。

依赖管理

Spring 通过分析构造函数、setter 或 @Autowired 注释的属性了解您的 classe 的依赖关系。请注意,如果您的 class 只有一个构造函数,Spring 会自动扫描它以了解相关性,即使它的顶部没有 @Autowired 也是如此。

在您的例子中,对于 CustomSpringEventListener,您有一个构造函数接收一个字符串参数。如果我们构建您的 CustomSpringEventListener 的依赖关系树,我们会得到类似的东西:

CustomSpringEventListener ---> String

因此,当 Spring 尝试创建您的 CustomSpringEventListener 时,它将查找 String 类型的 bean,因为,您的代码说:如果您想要创建一个object CustomSpringEventListener,你需要给一个名字,它是一个字符串。 但是我猜你的代码中没有 String 类型的 bean。

解决方案

第一次,用 @Component 注释你的 class CustomSpringEventListener 并删除你的属性和构造函数。

@Component
public class CustomSpringEventListener implements ApplicationListener<CustomSpringEvent> {

    @Override
    @EventListener
    public void onApplicationEvent(CustomSpringEvent event) {
        System.out.println("Received spring custom event - " + event.getMessage());
    }

}

第二次,如果您真的需要的话,找一个不同的方式在您的 class 中添加一个名字。

具有属性的侦听器

假设您需要一个更复杂的监听器,例如使用 ServiceA 的监听​​器。您可以执行以下操作:

@Service
public class ServiceA { ... }
@Component
public class CustomSpringEventListener implements ApplicationListener<CustomSpringEvent> {
    private ServiceA serviceA;

    public CustomSpringEventListener(ServiceA serviceA) {
        this.serviceA = serviceA;
    }

}

具有名称的同一个侦听器

您可以组合 @Configuration class 多次创建相同的 Listener。 让我们使用带有 name 属性的第一个监听器。

public class CustomSpringEventListener implements ApplicationListener<CustomSpringEvent> {
    private String name;

    public CustomSpringEventListener(String name) {
        this.name = name;
    }

    @Override
    @EventListener
    public void onApplicationEvent(CustomSpringEvent event) {
        System.out.println(name + " received spring custom event - " + event.getMessage());
    }

}

没有 @Component 注释,您可以使用 @Configuration class 来实例化您的监听器:

@Configuration
public ListenerConfig {

    public CustomSpringEventListener listenerA() {
        return new CustomSpringEventListener("listenerA");
    }

    public CustomSpringEventListener listenerB() {
        return new CustomSpringEventListener("listenerB");
    }

    public CustomSpringEventListener listenerC() {
        return new CustomSpringEventListener("listenerC");
    }

    ...
}

您可以混合 Spring 配置来执行您需要的任何配置。

希望对您有所帮助。