当前位置 博文首页 > 文章内容

    Spring的事件和监听器-同步与异步详解

    作者:shunshunshun18 栏目:未分类 时间:2021-12-28 15:25:23

    本站于2023年9月4日。收到“大连君*****咨询有限公司”通知
    说我们IIS7站长博客,有一篇博文用了他们的图片。
    要求我们给他们一张图片6000元。要不然法院告我们

    为避免不必要的麻烦,IIS7站长博客,全站内容图片下架、并积极应诉
    博文内容全部不再显示,请需要相关资讯的站长朋友到必应搜索。谢谢!

    另祝:版权碰瓷诈骗团伙,早日弃暗投明。

    相关新闻:借版权之名、行诈骗之实,周某因犯诈骗罪被判处有期徒刑十一年六个月

    叹!百花齐放的时代,渐行渐远!



    Spring的事件和监听器-同步与异步

    Application下抽象子类ApplicationContextEvent的下面有4个已经实现好的事件

    • ContextClosedEvent(容器关闭时)
    • ContextRefreshedEvent(容器刷新是)
    • ContextStartedEvent(容器启动时候)
    • ContextStoppedEvent(容器停止的时候)

    同样,这四个事件都继承了ApplicationEvent,如果我们想自定义事件,也可以通过继承ApplicationEvent来实现

    1、首先新建StartWorkflowEvent.java,

    继承ApplicationEvent抽象类

    public class StartWorkflowEvent extends ApplicationEvent {
        //存放构造器送入的值
        private String msg;
        //构造器参数可以随意设置,这里为了方便调试,设置为字符串
        public StartWorkflowEvent (String msg) {
            super(msg);
            this.msg=msg;
        }
        //自定义一个方法,这个方法也可以随意写,这里也是测试用
        public void myevent(){
            System.out.println("********My event**************");
            System.out.println(msg);
            System.out.println("*******************************");
        }
    }

    2、新建一个监听器StartWorkflowListener.java

    实现ApplicationListener<StartWorkflowEvent>

    /**
     * 发起流程事件监听
     */
    @Component("startWorkflowListener")
    public class StartWorkflowListener implements ApplicationListener<StartWorkflowEvent> {
     
        @Autowired
        private OaWorkflowHepler oaWorkflowHepler;
     
    //@Async注解异步调用时使用, 异步调用时, 需要在xml配置文件中添加 <task:annotation-driven />
    //  @Async
        @Override
        public void onApplicationEvent(StartWorkflowEvent event) {
            oaWorkflowHepler.start(event.getMsg());
        }
    }

    3、创建一个事件发布类EventPublisher.java

    /**
     * 发布事件
     */
    @Component("eventPublisher")
    public class EventPublisher {
     
        @Autowired
        private ApplicationContext applicationContext;
     
        /**
         * 发布事件
         * @param event
         */
        public void publishEvent(ApplicationEvent event) {
            applicationContext.publishEvent(event);
        }
    }

    4、相关的配置

    <task:annotation-driven />配置:

    • executor:指定一个缺省的executor给@Async使用。

    例子:

    <task:annotation-driven executor="asyncExecutor" />

    <task:executor />配置参数:

    • id:当配置多个executor时,被@Async("id")指定使用;也被作为线程名的前缀。
    • core size:最小的线程数,缺省:1
    • max size:最大的线程数,缺省:Integer.MAX_VALUE
    • queue-capacity:当最小的线程数已经被占用满后,新的任务会被放进queue里面,当这个 queue的capacity也被占满之后,pool里面会创建新线程处理这个任务,直到总线程数达到了max size,这时系统会拒绝这个任务并抛出TaskRejectedException异常(缺省配置的情况下,可以通过rejection-policy 来决定如何处理这种情况)。缺省值为:Integer.MAX_VALUE
    • keep-alive:超过core size的那些线程,任务完成后,再经过这个时长(秒)会被结束掉
    • rejection-policy:当pool已经达到max size的时候,如何处理新任务
    • ABORT(缺省):抛出TaskRejectedException异常,然后不执行
    • DISCARD:不执行,也不抛出异常
    • DISCARD_OLDEST:丢弃queue中最旧的那个任务
    • CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行

    Spring事件、异步监听

    使用事件的模式可以对系统进行解耦,事件源发布一个事件,

    事件监听器可以消费这个事件,而事件源不用关注发布的事件有哪些监听器,

    这可以对系统进行解耦

    在这里插入图片描述

    public class Mains extends ApplicationEvent {
        public Mains(Object name) {
            super(name);
            System.out.println(String.format("Hi,我是被监听的%s!",name));
        }
    }
    
    @Component
    public class ListenerMains {
        //@Async  // 开启异步就无法使用@Order(0)进行排序了
        @Order(0)
        @EventListener(Mains.class)
        public void listener(Mains mains){
            System.out.println("这是第一个监听类 "+mains.getSource());
        }
        //@Async
        @Order(1)
        @EventListener(Mains.class)
        public void listener2(Mains mains){
            System.out.println("这是第二个监听类 "+mains.getSource());
        }
        //@Async
        @Order(2)
        @EventListener(Mains.class)
        public void listener3(Mains mains){
            System.out.println("这是第三个监听类 "+mains.getSource());
        }
    }
    
    public class TestController {
        @Autowired
        GetAccessToken getAccessToken;
        @Autowired
        ApplicationEventPublisher publisher;
        @RequestMapping("test")
        public Object get() {
            publisher.publishEvent(new Mains("哈哈哈哈"));
        }
    }
    

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持IIS7站长之家博文。