• Spring 4.2框架中注释驱动的事件监听器详解


    事件交互已经成为很多应用程序不可或缺的一部分,spring框架提供了一个完整的基础设施来处理瞬时事件。下面我们来看看Spring 4.2框架中基于注释驱动的事件监听器。

    1、早期的方式

    在早期,组件要从Spring事件获知自定义域事件中获取通知,那么组件必须实现ApplicationListener接口并覆写onApplicationEvent方法。

    @Component
    class OldWayBlogModifiedEventListener implements
                            ApplicationListener<OldWayBlogModifiedEvent> {
        (...)
        @Override
        public void onApplicationEvent(OldWayBlogModifiedEvent event) {
            externalNotificationSender.oldWayBlogModified(event);
        }
    }
    

    上面的代码工作正常,但是它会针对每一个事件都创建一个新类,从而造成代码瓶颈。

    另外,我们的事件类继承了ApplicationEvent类——Spring应用中的事件基类。

    class OldWayBlogModifiedEvent extends ApplicationEvent {
        public OldWayBlogModifiedEvent(Blog blog) {
            super(blog);
        }
        public Blog getBlog() {
            return (Blog)getSource();
        }
    }
    

    请注意,在事件中使用Domain域对象有明显的缺点,在一些场景下不可用。这里只是做代码示例。

    顺便说一句,ExternalNotificationSender对象负责发送外部通知给已注册的用户(例如通过电子邮件、短信等方式)。

    2、注释驱动的事件监听器

    Spring 4.2框架值得注意的一点,用注释@EventListener注解任意的Spring组件。

    @EventListener
    public void blogModified(BlogModifiedEvent blogModifiedEvent) {
        externalNotificationSender.blogModified(blogModifiedEvent);
    }
    

    Spring会为事件创建一个ApplicationListener实例,并从方法参数中获取事件的类型。一个类中被事件注释的方法数量没有限制,所有相关的事件句柄都会分组到一个类中。

    3、有条件的事件处理

    为了使注释@EventListener的功能更强大,Spring 4.2支持用SpEL表达式表达事件类型的方式。假设以下是事件类:

    public class BlogModifiedEvent {
        private final Blog blog;
        private final boolean importantChange;
        public BlogModifiedEvent(Blog blog) {
            this(blog, false);
        }
        public BlogModifiedEvent(Blog blog, boolean importantChange) {
            this.blog = blog;
            this.importantChange = importantChange;
        }
        public Blog getBlog() {
            return blog;
        }
        public boolean isImportantChange() {
            return importantChange;
        }
    }
    

    要注意,在实际应用中可能不会有本文这样的层次结构的事件。 
    还要注意,用Groovy编写会更加简单。

    使用条件参数来阐述事件,重要的变化是:

    @EventListener(condition = "#blogModifiedEvent.importantChange")
    public void blogModifiedSpEL(BlogModifiedEvent blogModifiedEvent) {
        externalNotificationSender.blogModifiedSpEL(blogModifiedEvent);
    }
    

    4、宽松事件类型的层次结构

    Spring 4.2之前的版本,ApplicationEventPublisher只有在ApplicationEvent事件后发布其继承对象的能力。而在Spring 4.2版开始,此接口已经扩展到支持任意对象类型。在这种情况下,对象被封装到PayloadApplicationEvent和通过发送。

    //base class with Blog field - no need to extend `ApplicationEvent`
    class BaseBlogEvent {}
    class BlogModifiedEvent extends BaseBlogEvent {}
    //somewhere in the code
    ApplicationEventPublisher publisher = (...);    //injected
    publisher.publishEvent(new BlogModifiedEvent(blog)); //just plain instance of the event
    

    这一变化使得发布事件更容易。然而另一方面它可以导致事件跟踪变得更加困难,特别是在大型应用程序中。

    5、响应发布事件

    注释@EventListener还有一点需注意,在非空返回类型时,Spring会自动发布返回的事件。

    @EventListener
    public BlogModifiedResponseEvent blogModifiedWithResponse(BlogModifiedEvent blogModifiedEvent) {
        externalNotificationSender.blogModifiedWithResponse(blogModifiedEvent);
        return new BlogModifiedResponseEvent(
            blogModifiedEvent.getBlog(), BlogModifiedResponseEvent.Status.OK);
    }
    

    6、异步事件处理

    注释@EventListener还可以与注释@Async进行组合使用,以提供异步事件处理的机制。下面的代码中,指定的事件监听器既不会阻塞主要的代码执行,又不会被其它的监听器处理。

    @Async    //Remember to enable asynchronous method execution 
              //in your application with @EnableAsync
    @EventListener
    public void blogAddedAsync(BlogAddedEvent blogAddedEvent) {
        externalNotificationSender.blogAdded(blogAddedEvent);
    }
    

    为了使工作能够得到异步执行,通常还需在Spring项目的上下文中使用注释@EnableAsync。

    7、总结

    注释驱动的事件监听器是Spring框架4.2版中引入的新特性,它减少了Spring项目的样板代码,使得代码更加灵活,尤其是在小数量事件的需求时体现更为明显。

  • 相关阅读:
    百度地图 导航
    设置cookies第二天0点过期
    GDI+一般性错误(A generic error occurred in GDI+)
    图片上传裁剪(asp.net)
    LeetCode_7. Reverse Integer
    LeetCode_1. Two Sum
    JAVA 基础编程练习题50 【程序 50 文件 IO】
    JAVA 基础编程练习题49 【程序 49 子串出现的个数】
    JAVA 基础编程练习题48 【程序 48 加密】
    JAVA 基础编程练习题47 【程序 47 打印星号】
  • 原文地址:https://www.cnblogs.com/xunianchong/p/6862680.html
Copyright © 2020-2023  润新知