spring监听事件

1、spring-监听事件基本原理

  • Spring的事件监听机制和发布订阅机制是很相似的:发布了一个事件后,监听该类型事件的所有监听器会触发相应的处理逻辑

2、Spring 监听事件相关规范

在Spring中,事件监听机制主要涉及到了一下几个关键的规范(抽象类及接口):ApplicationEventApplicationListener ApplicationEventPublisher

  • ApplicationEvent: Spring的事件是符合jdk的规范的,这个抽象类继承了jdk内置的事件规范类EventObject(即jdk建议所有的事件都继承EventObject这个类)。ApplicationEvent是Spring家的事件规范。所以我们在自定义事件的时候,可以继承与ApplicationEvent,比如,Spring家自己关于容器上下文事件就又定义了一个容器上下文的时间规范ApplicationContextEvent,它同样是继承于ApplicationEvent的,只不过扩充了获取发出事件容器的方法;今后,我们同样可以在继承于ApplicationEvent的基础上定义自己的事件规范。

  • ApplicationListener:这是一个函数式接口,同样时事件监听器的规范,当监听到自己监听的事件类型时就会调用onApplicationEvent方法来执行监听逻辑

  • ApplicationEventPublisher:这同样是一个函数式接口,定义了事件发布的规范,任何的事件发布器ApplicationEventPublisher都是通过调用publishEvent来进行事件的发布

3、代码实现-自定事件

public class MyEvent extends ApplicationEvent {
     private user user;
     //注册方法也行。list<> 集合,对象
    public MyEvent(Object source, user user) {
        super(source);
        this.user = user;
    }

    public user getMessage() {
        return user;
    }
}

定义一个user实体类

@Data
public class user {
private String name;
private String age;

}

4、监听事件

  • springboot进行事件监听有四种方式,选择任意一种即可
  • 将监听器装载入spring容器(常用)
  • 通过@EventListener注解实现事件监听(常用)
  • 手工向ApplicationContext中添加监听器
  • 在application.properties中配置监听器
  • 4.1、 监听–ApplicationListener
@Component
@Slf4j
public class MyListener1 implements ApplicationListener<MyEvent> {
    @Override
    public void onApplicationEvent(MyEvent event) {
        //写自己的方法
       log.info("{}监听器1:监听到事件{}",MyListener1.class.getName(),event.getMessage());
        System.out.println("---------------------->监听器1:监听到事件");
    }
}
  • 4.2、 监听–注释
@Component
@Slf4j
public class MyListener2 {

    @EventListener(value = MyEvent.class)
    @Async
    public void listener(MyEvent event) {
        //写自己的方法
       log.info("{}监听器1:监听到事件{}", MyListener2.class.getName(),event.getMessage());
        System.out.println("---------------------->监听器1:监听到事件");
    }
}
  • 4.3、监听–配置文件
通过配置文application.properties中配置监听器: context.listener.classes=com.listener.MyListener1
  • 4.4、监听–手动添加监听
@SpringBootApplication
public class SpringListenerApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(SpringListenerApplication.class, args);
        // 添加监听器
        run.addApplicationListener(new MyListener1());
    }

}

5、发布事件

//使用 applicationContext  和ApplicationEventPublisher  都可以发布事件,人选则其一即可。
@RestController
@RequestMapping("/my")
public class MyController {
    @Autowired
    private ApplicationContext applicationContext;
    //@Autowired
   //  private ApplicationEventPublisher applicationEventPublisher;
    @RequestMapping("/test")
    public void test() {
        user user = new user();
        user.setName("GJ");
        user.setAge("12");
        System.out.println(applicationContext.getApplicationName());
        applicationContext.publishEvent(new MyEvent(this,user));
    //    applicationEventPublisher.publishEvent(new MyEvent(this,user));
    }
    }
//直接访问即可

6、工作中使用 ----发布者模式

@Component
public class ApplicationContextUtil implements ApplicationContextAware{

    private static ApplicationContext applicationContext;

    private ApplicationContextUtil() {
    }

    public static <T> T getBean(Class<T> clazz) throws BeansException{
        return applicationContext.getBean(clazz);
    }

    public static void publishEvent(Object event){;
        applicationContext.publishEvent(event);
    }

    public static ApplicationContext getApplicationContext(){
        return applicationContext;
    }

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        applicationContext = context;
    }

}

  • 6.1、添加 NoticeDto 类对MyEvent进行继承
@Data
public class NoticeDto extends MyEvent{
    private String noticeType;

    public NoticeDto(Object source) {
        super(source);
    }
}


@Data
public class MyEvent extends ApplicationEvent {
     private String message;
     //ApplicationEvent 需要有参的构造,所以必须调用super
     public MyEvent(Object source) {
          super(source);
     }
}
  • 6.2、监听器
@Component
@Slf4j
public class MyListener3 {

    @EventListener
    @Async
    //当然这个地方也可以使用NoticeDto  作为参数。
    public void listener(MyEvent event) {
//        假设 MyEvent 是 NoticeDto 的父类或接口,并且某个 MyEvent 类型的对象 event 实际上是 NoticeDto 的一个实例。
//        当这个对象被传递给 listener 方法时,它仍然保持着其作为 NoticeDto 实例的所有属性和值。
//        在方法内部,通过 (NoticeDto) event 进行向下转型,将这个对象视为 NoticeDto 类型,从而可以访问 NoticeDto 特有的属性和方法。
//        由于对象的内部状态在转换过程中没有改变,所以 NoticeDto 的属性会保留其原有的值。 总的来说,转换类型并没有改变对象的实际内容,只是改变了我们与对象交互的方式。
//        因此,NoticeDto 中的属性在转换后仍然保持其原有的值。
        NoticeDto event1 = (NoticeDto) event;
        //写自己的方法
       log.info("{}监听器:监听到事件{}", MyListener3.class.getName(),event.getMessage());
        System.out.println("---------------------->监听器:监听到事件");
        System.out.println(event.getMessage()+"\n"+event.getSource().getClass().getName());
        System.out.println(event1.getNoticeType());
        System.out.println(event1.getMessage());
    }
}
  • 6.3、访问测试:
    @RequestMapping("/test2")
    public void test2() {
        //不管怎么写,都会被监听,但必须传送一个 object source,传送什么无所谓。
        NoticeDto noticeDto = new NoticeDto(this);
        noticeDto.setNoticeType("123");
        noticeDto.setMessage("abc");
        ApplicationContextUtil.publishEvent(noticeDto);
    }
}
//结果为:
2024-07-09 23:43:57.180  INFO 8100 --- [nio-8888-exec-1] com.example.listener.MyListener3         : com.example.listener.MyListener3监听器:监听到事件abc
---------------------->监听器:监听到事件
abc
com.example.listener.MyController
123
abc

相关推荐

  1. spring监听事件

    2024-07-10 14:56:03       19 阅读
  2. Spring事件发布与监听

    2024-07-10 14:56:03       38 阅读
  3. Spring事件监听机制详解

    2024-07-10 14:56:03       21 阅读
  4. Spring boot 实现监听 Redis key 失效事件

    2024-07-10 14:56:03       48 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-10 14:56:03       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-10 14:56:03       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-10 14:56:03       45 阅读
  4. Python语言-面向对象

    2024-07-10 14:56:03       55 阅读

热门阅读

  1. 网络基础——udp协议

    2024-07-10 14:56:03       18 阅读
  2. Python从Excel表中查找指定数据填入新表

    2024-07-10 14:56:03       18 阅读
  3. 数据库和缓存基础(mysql,redis等)

    2024-07-10 14:56:03       17 阅读
  4. TortoiseSVN 使用教程

    2024-07-10 14:56:03       21 阅读
  5. led_strip例程分析

    2024-07-10 14:56:03       15 阅读
  6. 一个用于在虚拟桌面下跑chrome的docker镜像

    2024-07-10 14:56:03       17 阅读
  7. 东方通Tongweb发布vue前端,HSTS漏洞修复

    2024-07-10 14:56:03       17 阅读
  8. 【无标题】

    2024-07-10 14:56:03       17 阅读
  9. Redis教程(二十三):Redis的底层数据结构

    2024-07-10 14:56:03       21 阅读
  10. 博客网站目录网址导航自适应主题php源码

    2024-07-10 14:56:03       18 阅读