springboot2自定义监听器

好久不见,前段时间本来写了篇nginx的配置,但是中途被耽误了.然后就是思路断了,我就索性删除掉了.话不多说,今天这个文章主要是记录下如何在springboot写一个自定义监听器.

下面的内容我们会介绍一下spring的事件机制,然后跟大家一起温习下观察者模式,最后就是写一个自定义监听器.

Spring框架中的事件机制

我们都知道事件机制是spring框架中的一个重要特性.(ps:不知道也没事,这里就知道了~哈哈哈)

事件机制是基于我们所知道的设计模式--观察者模式实现的,它可以实现应用程序中的解耦,提高代码的可维护性和可扩展性.简单来理解就是它的侵入性不强,就好比是我们电脑外接设备,这些设备不接行不行?那肯定行呀,外接的目的就是扩展我们电脑本来没有的功能或者说是完善或者强化,一样的道理用于解释事件机制,它并不是强耦合的,举个具体的场景:

比如我们的某个web系统,我们有个用户修改密码的功能,修改完密码我们需要短信通知用户,并且记录关键性日志.实际上,我们的核心功能是改密码,改完密码实际上这件事就已经算结束了,那么通知用户和记录日志都是额外的附件的功能(这是可做可不做的),这个时候,我们就可以用事件机制来处理这一块逻辑,假如以后我们不需要通知用户了或者不需要记录日志了,那么只需要将这个事件移除就可以了,并不会跟我们的业务代码耦合在一起.

我从掘金社区那边引用了两张流程图来帮助理解上面这段例子**(因为我觉得图很清晰,便于理解,如有侵权,请联系删除**)

修改密码多个服务

见上图,我们需要调用多个服务来实现一个修改密码的功能.(这实际上就让这个密码修改的功能变得很重)

修改密码加入事件机制后

见上图,我们用了事件机制后,我们做完了密码修改之后,只需要发布一个事件就好了,之后就让我们的事件监听器去处理,这样子我们模块之间就实现了解耦.

观察者模式

我们在上文说到了Spring的事件机制实际上是基于观察者模式来实现的,那么我们就借机来温习下观察者模式(不知道的同学们也可以学习下)

观察者模式是干嘛用的

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态上发生变化时,会通知所有观察者对象,让他们能够自动更新自己。

观察者模式有哪些角色呢

  1. 抽象主题角色

    把所有观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者角色,一般用一个抽象类或接口来实现。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    public interface AbstractSubject {
    /**
    * 增加观察者
    *
    * @param observer observer
    * @author gcoder
    * @date 2023-06-25
    */
    public void addObserver(AbstractObserver observer);

    /**
    * 删除观察者
    *
    * @param observer observer
    * @author gcoder
    * @date 2023-06-25
    */
    public void removeObserver(AbstractObserver observer);

    /**
    * 通知
    *
    * @param observer observer
    * @author gcoder
    * @date 2023-06-25
    */
    public void notification();
    }
  2. 抽象观察者角色

    为所有具体的观察者定义一个接口,在得到主题的通知时更新自己

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public interface AbstractObserver {
    /**
    * 更新
    *
    * @author gcoder
    * @date 2023-06-25
    */
    public void update();
    }
  3. 具体主题角色

    在具体主题内部状态改变时,给所有登记过的观察者发出通知,具体主题角色通常用一个子类实现。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public class ConcreteSubject implements AbstractSubject {
    List<AbstractObserver> list = new ArrayList<AbstractObserver>();
    @Override
    public void addObserver(AbstractObserver observer) {
    list.add(observer);
    }
    @Override
    public void removeObserver(AbstractObserver observer) {
    list.remove(observer);
    }
    // 状态改变了,所有观察者更新自己的界面
    @Override
    public void notification() {
    for (AbstractObserver abstractObserver : list) {
    abstractObserver.update();
    }
    }
    }
  4. 具体观察者角色

    该角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调,如果需要,具体观察者角色可以有一个指向具体主题角色的引用,通常用一个子类实现

    1
    2
    3
    4
    5
    6
    public class Observer1 implements AbstractObserver {
    @Override
    public void update() {
    System.out.println("通知:明天特殊原因,不需要上班了~");
    }
    }

下面我们的测试类内容如下

1
2
3
4
5
6
7
8
9
public class Client(){
public static void main(String[] args) {
AbstractSubject subject = new ConcreteSubject();
subject.addObserver(new Observer1());
subject.addObserver(new Observer2());
subject.addObserver(new Observer3());
subject.notification();
}
}

以上,就是我们的观察者模式的示例代码了.当然了,我们的Java其实本身也有内置的观察者模式框架,有兴趣的同学们可以去搜搜ObservableObserver.

Springboot的自定义监听器

最后,我们通过springboot来实现一个自定义监听器.一共分成三个部分:自定义事件和事件监听和事件发布.

自定义事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyEvent extends ApplicationEvent {
/**
* 消息
*/
private final String message;
public MyEvent(Object source,String message) {
super(source);
this.message = message;
}

public String getMessage() {
return message;
}
}

事件监听

这里就是处理监听到之后的后续业务操作逻辑

1
2
3
4
5
6
7
@Component
public class MyEventListener implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
System.out.println("接收到消息:"+event.getMessage());
}
}

事件发布

1
2
3
4
5
6
7
@Component
public class MyEventListener implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
System.out.println("接收到消息:"+event.getMessage());
}
}

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
@RestController
@RequestMapping("/demo/")
public class HelloController {
@Autowired
private MyEventPublisher publisher;

@GetMapping("say")
public String sayHello(String name) {
System.out.println("name = " + name);
publisher.sendMessage(name);
return "Hello Event";
}
}

通过上述的方式,我们就可以在某些restful接口或者其他的业务处理上加一些事件,用来处理除了主干功能之外的业务.

写在最后

实际上关于Springboot的事件机制还有很多其他的用法,下一个篇幅我们来一起来探索下事务监听以及了解下监听器的源码是如何去做处理的~那就先这样咯!

Bye.


springboot2自定义监听器
https://gcoder5.com/2023/06/25/springboot2自定义监听器/
作者
Gcoder
发布于
2023年6月25日
许可协议