首页 > 其他分享 >spring中的ApplicationEventPublisher的使用

spring中的ApplicationEventPublisher的使用

时间:2023-08-27 12:33:21浏览次数:34  
标签:sender ApplicationEventPublisher spring void 观察者 class 使用 new public

spring中的ApplicationEventPublisher 是spring对发布订阅模式的一种支持,要了解它的作用和使用需要先了解下观察者模式发布订阅模式

目录

一、观察者模式

观察者模式中涉及观察者,被观察者两种角色,其中被观察者中会持有多个观察者对象,当自己的状态发生改变时会通知所有的观察者。

下面举一个银行转账的例子来说明,银行账户发生变动时要分别通过短信和app信息两种方式通知客户,使用观察者模式来设计这个案例。

先抽象出一个发送信息的接口

//发送信息的接口
public interface Sender {
    
    void send();
}

再分别创建出发送短信和app信息的类

发送短信

public class SmsSender implements Sender{
    @Override
    public void send() {
        System.out.println("发送短信");
    }
}

发送app信息

public class AppSender implements Sender{
    @Override
    public void send() {
        System.out.println("发送app信息");
    }
}

再创建一个账户类,账户类中会持有多个sender对象,在自己状态发生变化时会通知所有的sender

public class BankAccount {
    //持有多个sender对象
    private List<Sender> senders = new ArrayList<>();
    
    public void addSender(Sender sender){
        this.senders.add(sender);
    }
    
    //通知所有的观察者
    private void send(){
        for (Sender sender : this.senders) {
            sender.send();
        }
    }
    
    public void transfer(){
        System.out.println("发起转账");
        send();
    }
}

再创建测试类进行测试

    public static void main(String[] args) {
        //创建被观察者
        BankAccount bankAccount = new BankAccount();
        //创建观察者
        SmsSender smsSender = new SmsSender();
        AppSender appSender = new AppSender();
        bankAccount.addSender(smsSender);
        bankAccount.addSender(appSender);

        //改变被观察者的状态
        bankAccount.transfer();
    }

运行后控制台会依次输出

发起转账
发送短信
发送app信息

这就是观察者模式的一个简单运用,在这种模式下被观察者不需要关注观察者的具体逻辑,实现了逻辑上的解耦。

但是被观察者内部还是需要持有观察者的对象,所以在这种模式的基础上发展出了一种完全解耦的模式即

发布订阅模式,在标准设计模式中实际是没有发布订阅模式的,它可以看做是观察者模式的一种变种。

二、发布订阅模式

发布订阅模式通过一个发布者角色实现了观察者和被观察者的完全解耦,发布者相等于一个中转站,所有观察者都在发布者中注册,被观察者状态发生改变时通过发布者来通知所有的观察者但被观察者本身并不知道有多少观察者的存在。下面用发布订阅模式来改造下第一节的例子

发布者

public class BankPublisher {
    //持有多个sender对象
    private List<Sender> senders = new ArrayList<>();

    public void addSender(Sender sender){
        this.senders.add(sender);
    }

    //通知所有的观察者
    public void send(){
        for (Sender sender : this.senders) {
            sender.send();
        }
    }
}

现在账户类中不再持有所有观察者只需要持有发布者对象就够了

public class BankAccount {
    //持有发布者对象
    private BankPublisher publisher;
    
    public void setPublisher(BankPublisher publisher){
        this.publisher = publisher;
    }

    public void transfer(){
        System.out.println("发起转账");
        publisher.send();
    }
}

测试类

public class Test {
    public static void main(String[] args) {
        //创建被观察者
        BankAccount bankAccount = new BankAccount();
        //创建观察者
        SmsSender smsSender = new SmsSender();
        AppSender appSender = new AppSender();
        //创建发布者
        BankPublisher publisher = new BankPublisher();
        publisher.addSender(smsSender);
        publisher.addSender(appSender);

        //被观察者绑定publish
        bankAccount.setPublisher(publisher);

        //改变被观察者的状态
        bankAccount.transfer();
    }
}

这种模式相比于观察者模式的优势就是完全解耦了观察者和被观察者

三、spring中的ApplicationEventPublisher

ApplicationEventPublisher是spring提供的一个事件发布器使用它可以实现发布订阅模式,

下面在spring环境中实现下上边的例子.

bankService

public class BankAccountService {
    //注入事件发布器
    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;
    
    public void transfer(){
        System.out.println("发起转账");
        
        // 参数是需要传递给订阅者的信息
        applicationEventPublisher.publishEvent(new BankEvent("转账"));
    }
}

BankEvent封装了需要传递给订阅者的消息

import org.springframework.context.ApplicationEvent;

public class BankEvent extends ApplicationEvent {

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

两个观察者需要实现ApplicationListener接口

import org.springframework.context.ApplicationListener;

public class SmsListener implements ApplicationListener<BankEvent> {
    @Override
    public void onApplicationEvent(BankEvent event) {
        System.out.println("发送短信:"+event.getSource());
    }
}
import org.springframework.context.ApplicationListener;

public class AppListener implements ApplicationListener<BankEvent> {
    @Override
    public void onApplicationEvent(BankEvent event) {
        System.out.println("发送app消息:"+event.getSource());
    }
}

在测试类中配置spring

public class Test2 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        BankAccountService bankAccountService = applicationContext.getBean(BankAccountService.class);
        bankAccountService.transfer();
    }


    static class MyConfig {

        @Bean
        public BankAccountService bankAccountService () {
            return new BankAccountService();
        }

        @Bean
        public SmsListener smsListener() {
            return new SmsListener();
        }

        @Bean
        public AppListener appListener(){
            return new AppListener();
        }
    }
}

这样也能达到上边第二节的效果,这就是spring中对发布订阅模式的支持。

标签:sender,ApplicationEventPublisher,spring,void,观察者,class,使用,new,public
From: https://www.cnblogs.com/chengxuxiaoyuan/p/17660127.html

相关文章

  • 使用 XStream实现JavaBean 与 XML/JSON 之间相互转换
    XML和JSON是当今常用的两种数据描述与传输的格式,特别是涉及到JS时使用JSON颇为频繁。自然,在Java的世界里少不了完成JavaBean与这两种格式相互转换的组件,那就是XStream和JSON-lib。这里我简单记下XStream的用法。其实相类似的工具早已有之。如果用过DWR的同志,一定有印像,DWR进行远程......
  • jackson的使用
    1、jackson能做什么?Jackson被称为"JavaJSON库"或"Java的最佳JSON解析器"。不仅如此,Jackson还是一套适用于Java(和JVM平台)的数据处理工具,除了能处理json格式数据以外,还能处理csv、xml、(java)properties等格式数据。2、使用方法处理json数据maven中加入依赖<......
  • 如何安装和使用 Latte Dock
    你知道什么是“停靠区Dock”吧,它通常是你的应用程序“停靠”的底栏,以便快速访问。许多发行版和桌面环境都提供了某种停靠实现。如果你的发行版没有“停靠区Dock”,或者你想尝试一些新的停靠应用,LatteDock是一个不错的选择。它类似于macOS上的停靠区,每次你用鼠标悬停在任何停......
  • SpringBoot - 事务处理
    事务介绍是一组操作的集合,它是一个不可分割的工作单位,这些操作要么同时成功,要么同时失败Spring事务管理:注解:@Transactional位置:业务层的方法上、类上、接口上作用:将当前方法交给spring进行事务管理,方法执行前,开始事务。成功执行完毕,提交事务,出现异常,回滚事务引入案......
  • 在Jupyter中使用AI写代码,如有神助,太惊艳了
    昨晚看到一个可以在JupyterLab中使用的AI代码辅助工具jupyter-ai,它的交互确实非常棒,可以直接聊天,也可以就笔记中的代码提问,最出彩的是生成笔记功能,还是蛮惊艳的。这里就极简介绍一下安装及用法第一步是创建环境并安装condacreate-njupyter-aipython=3.11condaactivateju......
  • 上市公司绿色创新效率数据计算(text mining方法的使用)
    需求:工作中需要计算上市公司绿色创新效率数据,需要首先利用text_preprocessing对文本提取值进行预处理,然后通过Textmining方法进行转换后计算处理,最后利用效率法来进行综合计算和归类存储,用于后续的深度数据挖掘。解决:importnltkfromnltk.corpusimportstopwordsfromnltk.tok......
  • Java使用Jsch执行Shell命令
    JSch是SSH2的纯Java实现。JSch允许您连接到sshd服务器并使用端口转发,X11转发,文件传输等,您可以将其功能集成到您自己的Java程序中。JSch获得BSD格式许可证。最初,我们开发这些东西的动机是允许我们的纯JavaX服务器WiredX的用户享受安全的X会话。所以,我们的努力主要是为了实现用......
  • 使用pdb调试openstack (How to debug openstack using pdb )
    终于摸索出了一个调试openstack的简单方法,使用pdb进行单步调试,对于分析代码很有帮助。注意,这个方法只适用于用devstack安装的openstack。调试主要是使用了一个脚本,这个脚本不记得是从哪下载的了,是用来重启使用devstack安装的openstack的各个服务的,后来,我又结合devstack的stack.sh和......
  • 使用 Java 生成二维码图片
    0x01准备(1)软件版本IntelliJIDEA2023.1.3JDK18Tomcat10.1.11Maven3.8.6(2)技术栈servletzxing谷歌项目生成黑白二维码并可以附上logoqrcodegithub开源项目基于并拓展zxing(3)创建项目创建空项目在菜单栏-文件-项目结构中设置JDK及语言级别......
  • 你的旧电脑是 “过时” 了,还是使用 Linux 的机会?
    导读很多时候,老旧的电脑往往被打上“过时”的标签。Linux 改变了这一现状。翻新旧电脑,让它重新为需要它的人所用。你可能经常听到有人说某个电脑、平板电脑或智能手机“过时了”。当你听到这样的说法时,花一分钟问问自己:“这个人说的是个人观点还是事实?”很多时候他......