Spring事件
ApplicationEvent类和ApplicationListener接口,可以实现ApplicationContext事件处理。
如果容器中有一个ApplicationListener Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListener Bean将自动被触发。这种事件机制都必须需要程序显示的触发。
事件原理
ApplicationContext事件机制是观察者设计模式的实现
https://zhuanlan.zhihu.com/p/27763120
内置事件
其中spring有一些内置的事件,当完成某种操作时会发出某些事件动作。比如监听ContextRefreshedEvent事件,当所有的bean都初始化完成并被成功装载后会触发该事件,实现ApplicationListener
内置事件实例
@Component
public class TestApplicationListener implements ApplicationListener<ContextRefreshedEvent>{
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
System.out.println(contextRefreshedEvent);
System.out.println("TestApplicationListener............................");
}
}
public class OpenApiAccessLogEngine extends BaseEngine implements ApplicationListener<ContextClosedEvent> {
@Override
public void onApplicationEvent(@NonNull ContextClosedEvent event) {
this.running = false;
taskExecutor.shutdown();
}
}
自定义事件
同样事件可以自定义、监听也可以自定义,完全根据自己的业务逻辑来处理。
获取 Spring 容器
/**
* 持有spring的上下文对象
*
* @author lennon
*
*/
@Component
public class SpringContextHolder implements ApplicationContextAware{
private static ApplicationContext applicationContext = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
SpringContextHolder.applicationContext = applicationContext;
}
public static Object getBean(String name){
return SpringContextHolder.applicationContext.getBean(name);
}
public static ApplicationContext getApplicationContext() {
return SpringContextHolder.applicationContext;
}
}
事件类```java
import org.springframework.context.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(“*“); } }
<a name="qFU9r"></a>
##
<a name="ToiMG"></a>
## 监听类
Spring 提供的ApplicationEvent & Listener有3种实现方式:
<a name="P7WJ6"></a>
### 1. 实现ApplicationListener接口方式
通过注解@Component注册进 Spring容器
```java
@EnableAsync
@Component("startWorkflowListener")
public class StartWorkflowListener implements ApplicationListener<StartWorkflowEvent> {
@Async//开启异步执行
@Override
public void onApplicationEvent(StartWorkflowEvent event) {
for (int i = 0; i < 3; i++) {
try {
TimeUnit.SECONDS.sleep(1);
System.out.println("--------");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
event.myevent();
}
}
2. @EventListener 注解的方式
@Component
public class TestApplicationListener2{
//@Async
@EventListener
public void onApplicationEvent(StartWorkflowEvent event) {
System.out.println("step2:code is:\t" + event.getCode() + ",\tmessage is:\t" + event.getMessage());
}
}
3. 实现SmartApplicationListener接口(事件监听顺序)
在实现了SmartApplicationListener的监听器中,我们通过重写GetOrder方法来修改不同监听器的顺序,优先级越小,则越先被调用。通过配置不同的优先级,且让监听器之间阻塞调用。我们就能实现流水线式的有序事件调用,这在实际应用场景中还是蛮有意义的
/**
* 发起流程事件监听
*/
@EnableAsync
@Component("startWorkflowListener")
public class StartWorkflowListener implements SmartApplicationListener {
@Override
public int getOrder() {
return 2;
}
/**
* 指定支持哪些类型的事件
*/
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> aClass) {
return aClass == StartWorkflowEvent.class;
}
/**
* 指定支持发生事件所在的类型
*/
@Override
public boolean supportsSourceType(Class<?> aClass) {
return true;
}
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
StartWorkflowEvent event = (StartWorkflowEvent) applicationEvent;
//发送短信
System.out.println(event.getTimestamp());
}
}
事件发布
事件是同步处理的,当事件处理完成后,才会执行发布事件后的内容
public class SpringTest {
public static void main(String args[]){
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
StartWorkflowEvent startWorkflowEvent = new StartWorkflowEvent("你好");
SpringContextHolder.getApplicationContext().publishEvent(startWorkflowEvent);
// 事件执行完成后, 同步执行下面代码
for (int i = 0; i < 20; i++) {
try {
TimeUnit.SECONDS.sleep(1);
System.out.println("1111");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
或直接注入发布类
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
参考文章:
「colie_li」 https://blog.csdn.net/liyantianmin/article/details/81017960