spring发布事件的3种方式

通过Spring自身的事件机制来发布事件。包括同步方式,同步注解方式,异步注解方式:

1)同步方式。

首先定义事件类:通过继承ApplicationEvent来将普通对象设置成Spring事件

package com.wxq.ssm.common.event;

import org.springframework.context.ApplicationEvent;

/**
 * @author xueqin
 * @Description: Modified By:
 * Created by xueqin on 18/3/31.
 */
public class BlackListEvent extends ApplicationEvent {
    private final String address;
    private final String test;

    public BlackListEvent(Object source, String address, String test) {
        super(source);
        this.address = address;
        this.test = test;
    }

    public String getAddress() {
        return address;
    }

    public String getTest() {
        return test;
    }
}
其次定义事件的监听者:通过实现ApplicationListener<T>接口来表明要监听的事件类型,并来执行具体的任务。这里用sout输出来模拟。
package com.wxq.ssm.common.listener;

import com.wxq.ssm.common.event.BlackListEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

/**
 * @author xueqin
 * @Description: Modified By:
 * Created by xueqin on 18/3/31.
 */
public class BlackListNotifier implements ApplicationListener<BlackListEvent> {

    private String notificationAddress;

    public void setNotificationAddress(String notificationAddress) {
        this.notificationAddress = notificationAddress;
    }
    @Override
    public void onApplicationEvent(BlackListEvent event) {
        System.out.println(event.getAddress());
        System.out.println(event.getTest());
    }
}
再次定义接口发布事件:通过实现ApplicationEventPublisherAware接口来发布事件

package com.wxq.ssm.common.event;

import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author xueqin
 * @Description: Modified By:
 * Created by xueqin on 18/3/31.
 */
@Component
public class EmailService implements ApplicationEventPublisherAware {

    private List<String> blackList;
    private ApplicationEventPublisher publisher;

    public void setBlackList(List<String> blackList) {
        this.blackList = blackList;
    }
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }
    public void sendEmail(String address, String text) {
        if (blackList.contains(address)) {
            BlackListEvent event = new BlackListEvent(this, address, text);
            publisher.publishEvent(event);
            return;
        }
        // send email...
    }
}
ApplicationEventPublisher来发布自己定义的事件。
最后就是对事件bean的定义my-event.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context ="http://www.springframework.org/schema/context"
       xmlns:task ="http://www.springframework.org/schema/task"
       xmlns:cache="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.1.xsd
         http://www.springframework.org/schema/task
         http://www.springframework.org/schema/task/spring-task-3.1.xsd
         http://www.springframework.org/schema/cache
       http://www.springframework.org/schema/cache/spring-cache.xsd">

    <!-- 自动搜索并注入 -->
    <bean id="emailService" class="com.wxq.ssm.common.event.EmailService">
        <property name="blackList">
            <list>
                <value>known.spammer@example.org</value>
                <value>known.hacker@example.org</value>
                <value>john.doe@example.org</value>
                <value>127.0.0.2</value>
            </list>
        </property>
    </bean>
 
<bean id="blackListNotifier" class="com.wxq.ssm.common.listener.AnotationBlackListNotifier">
    <property name="notificationAddress" value="blacklist@example.org"/>
</bean>
<bean id="blackListNotifier1" class="com.wxq.ssm.common.listener.BlackListNotifier">
    <property name="notificationAddress" value="blacklist@example.org"/>
</bean>

<!-- 启动对@AspectJ注解的支持 --> < context :component-scan base-package ="com.wxq.ssm.*" /> < task :annotation-driven /> </ beans >
那我们的测试类如下:

public class EventSynTest {
    public static void main(String[] args) {
        String file="file:/Users/xueqin/spring_learn/spring-mybatis-maven/src/main/resources/my-event.xml";
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(file);
        EmailService emailService = (EmailService) context.getBean("emailService");

       emailService.sendEmail("127.0.0.2","this is a syn event listener");

        System.out.println("dddddddddddd");
        System.out.println("fefefefefefefe");

}

最后再执行sendEmail方法时,会发布事件,然后会打印输出address和test.

------------------------

第二种自然是基于注解的方式来发布事件了。

事件对象不需要修改。

我们要做的就是对监听对象的修改:

package com.wxq.ssm.common.listener;

import com.wxq.ssm.common.event.BlackListEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

/**
 * @author xueqin
 * @Description: Modified By:
 * Created by xueqin on 18/3/31.
 */
@Component
public class AsynBlackListNotifier {
    private String notificationAddress;

    public void setNotificationAddress(String notificationAddress) {
        this.notificationAddress = notificationAddress;
    }

    @EventListener
    public void processBlackListEvent(BlackListEvent event) {
        // notify appropriate parties via notificationAddress...
        System.out.println(event.getAddress());
        try {
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("this is a  ASYN EventListener");
        System.out.println(event.getTest());
    }
}
不在实现接口来完成监听,而是通过注解@EventListener来实现监听,

然后因为EventListener作为主键,是需要开启包扫描spring才能知道你是有个事件监听。否则不起作用。

其他的测试方法啥的都是一样的

------------------------

最后就是异步方式来发布事件。因为前两种并不是异步的,你需要等待知道事件完成,才会返回。当然和我们想要的不一样。

那么异步方式也很简单。

只是对监听类加注解:

package com.wxq.ssm.common.listener;

import com.wxq.ssm.common.event.BlackListEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

/**
 * @author xueqin
 * @Description: Modified By:
 * Created by xueqin on 18/3/31.
 */
@Component
public class AsynBlackListNotifier {
    private String notificationAddress;

    public void setNotificationAddress(String notificationAddress) {
        this.notificationAddress = notificationAddress;
    }

    @EventListener
    @Async
    public void processBlackListEvent(BlackListEvent event) {
        // notify appropriate parties via notificationAddress...
        System.out.println(event.getAddress());
        try {
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("this is a  ASYN EventListener");
        System.out.println(event.getTest());
    }
}

@Asyn就是告诉Spring,这个事件的执行需要用异步的方式来完成。

当然你只给加这一个注解是不够的,因为spring的异步同样需要执行器来执行。所以我们需要在配置文件中加task注解的配置,才会起作用。

<!-- 启动对@AspectJ注解的支持 -->
<context:component-scan  base-package ="com.wxq.ssm.*"/>
   <task:annotation-driven/>
这个注解加了后,就会执行包扫描,和开启异步任务的spring支持。当然你也可以根据实际情况对task来定制。从而很好的完成事件。

包括线程池的大小,等待时长,等待队列的长度,异常机制等。

好了到此就结束了。其实spring的事件方式,如果能理解第一种,那之后的就都简单了。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值