通过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的事件方式,如果能理解第一种,那之后的就都简单了。