Spring的事件和监听器-同步与异步详解
目录
- Spring的事件和监听器-同步与异步
- 1、首先新建StartWorkflowEvent.java,
- 2、新建一个监听器StartWorkflowListener.java
- 3、创建一个事件发布类EventPublisher.java
- 4、相关的配置
- Spring事件、异步监听
- 这可以对系统进行解耦
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
:最小的线程数,缺省:1max size
:最大的线程数,缺省:Integer.MAX_VALUEqueue-capacity
:当最小的线程数已经被占用满后,新的任务会被放进queue里面,当这个 queue的capacity也被占满之后,pool里面会创建新线程处理这个任务,直到总线程数达到了max size,这时系统会拒绝这个任务并抛出TaskRejectedException异常(缺省配置的情况下,可以通过rejection-policy 来决定如何处理这种情况)。缺省值为:Integer.MAX_VALUEkeep-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("哈哈哈哈")); } }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。
赞 (0)