Spring事件

标准和自定义事件官方文档

ApplicationEvent类ApplicationListener接口,可以实现ApplicationContext事件处理。

如果容器中有一个ApplicationListener Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListener Bean将自动被触发。这种事件机制都必须需要程序显示的触发。

事件原理

ApplicationContext事件机制是观察者设计模式的实现
https://zhuanlan.zhihu.com/p/27763120

内置事件

其中spring有一些内置的事件,当完成某种操作时会发出某些事件动作。比如监听ContextRefreshedEvent事件,当所有的bean都初始化完成并被成功装载后会触发该事件,实现ApplicationListener接口可以收到监听动作,然后可以写自己的逻辑。
image.png

内置事件实例

  1. @Component
  2. public class TestApplicationListener implements ApplicationListener<ContextRefreshedEvent>{
  3. @Override
  4. public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
  5. System.out.println(contextRefreshedEvent);
  6. System.out.println("TestApplicationListener............................");
  7. }
  8. }
  1. public class OpenApiAccessLogEngine extends BaseEngine implements ApplicationListener<ContextClosedEvent> {
  2. @Override
  3. public void onApplicationEvent(@NonNull ContextClosedEvent event) {
  4. this.running = false;
  5. taskExecutor.shutdown();
  6. }
  7. }

自定义事件

同样事件可以自定义、监听也可以自定义,完全根据自己的业务逻辑来处理。

获取 Spring 容器

  1. /**
  2. * 持有spring的上下文对象
  3. *
  4. * @author lennon
  5. *
  6. */
  7. @Component
  8. public class SpringContextHolder implements ApplicationContextAware{
  9. private static ApplicationContext applicationContext = null;
  10. @Override
  11. public void setApplicationContext(ApplicationContext applicationContext)
  12. throws BeansException {
  13. SpringContextHolder.applicationContext = applicationContext;
  14. }
  15. public static Object getBean(String name){
  16. return SpringContextHolder.applicationContext.getBean(name);
  17. }
  18. public static ApplicationContext getApplicationContext() {
  19. return SpringContextHolder.applicationContext;
  20. }
  21. }

事件类```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(“*“); } }

  1. <a name="qFU9r"></a>
  2. ##
  3. <a name="ToiMG"></a>
  4. ## 监听类
  5. Spring 提供的ApplicationEvent & Listener有3种实现方式:
  6. <a name="P7WJ6"></a>
  7. ### 1. 实现ApplicationListener接口方式
  8. 通过注解@Component注册进 Spring容器
  9. ```java
  10. @EnableAsync
  11. @Component("startWorkflowListener")
  12. public class StartWorkflowListener implements ApplicationListener<StartWorkflowEvent> {
  13. @Async//开启异步执行
  14. @Override
  15. public void onApplicationEvent(StartWorkflowEvent event) {
  16. for (int i = 0; i < 3; i++) {
  17. try {
  18. TimeUnit.SECONDS.sleep(1);
  19. System.out.println("--------");
  20. } catch (InterruptedException e) {
  21. e.printStackTrace();
  22. }
  23. }
  24. event.myevent();
  25. }
  26. }

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