Java两大工具库Commons和Guava使用示例详解

目录
  • 正文
  • 先定义观察者
    • 然后定义账户类
    • 最后实现事件总线
  • 创建观察者接口和具体观察者
    • 创建Subject:

正文

除了操作集合、限流和缓存,Guava还有另一个隐秘的功能:事件总线EventBus机制——是发布-订阅模式的实现,不需要显式地注册回调——比观察者模式更灵活。

EventBus是在单体架构内实现松耦合的一种很好的手段,通过它可以实现与业务逻辑无关的事件监听和消费。Guava提供的事件总线EventBus分为两种:

  • 1、同步事件EventBus,主要用于单线程环境;
  • 2、异步事件AsyncEventBus,主要用于多线程环境。

可以稍稍回顾一下观察者模式。

在支付系统的设计模式中,当完成交易后,需要给用户发送通知时就使用到了观察者模式,怎么做的呢?

  • 1、定义账户观察者接口及其子接口支付观察者和积分观察者;
  • 2、支付抽象类实现这两个子接口,具体支付类阿里支付、微信支付和余额支付,也都分别实现这两个子接口;
  • 3、在账户类中加入观察者接口列表,并增加注册、删除和调用观察者接口的方法;
  • 4、在支付时将各类支付方式注册到账户的观察者列表中;
  • 5、在交易完成后,就可以调用账户的调用观察者接口的方法,实现回调。

观察者模式的实现稍嫌麻烦。

既然用观察者模式实现比较麻烦,那不妨换个思路,用Guava EventBus来实现,而且无需继承任何接口。调用、发送回调通知同样也很简单,用EventBus把支付回调再来实现一遍。

先定义观察者

/**
 * 支付宝观察者
 *
 * @author 湘王
 */
public class AliPayObserver {
    // 标记当前订阅者是线程安全的,支持并发接收消息
    @AllowConcurrentEvents
    @Subscribe
    public void pay(Account account) {
        if (account.getName().equalsIgnoreCase("ALI")) {
            System.out.println("支付宝 >>>>>> 已付款");
            System.out.println(account.getMessage());
        }
    }
}
/**
 * 微信支付观察者
 *
 * @author 湘王
 */
public class WeixinObserver {
    // 标记当前订阅者是线程安全的,支持并发接收消息
    @AllowConcurrentEvents
    @Subscribe
    public void pay(Account account) {
        if (account.getName().equalsIgnoreCase("WEIXIN")) {
            System.out.println("微信 >>>>>> 已付款");
            System.out.println(account.getMessage());
        }
    }
}
/**
 * 余额支付观察者
 *
 * @author 湘王
 */
public class YuePayObserver {
    // 标记当前订阅者是线程安全的,支持并发接收消息
    @AllowConcurrentEvents
    @Subscribe
    public void pay(Account account) {
        if (account.getName().equalsIgnoreCase("YUE")) {
            System.out.println("余额 >>>>>> 已付款");
            System.out.println(account.getMessage());
        }
    }
}

然后定义账户类

/**
 * 账户
 *
 * @author 湘王
 */
public class Account {
    private String name;
    private double amount;
    private Date date;
    public Account(String name, double amount, Date date) {
        this.name = name;
        this.amount = amount;
        this.date = date;
    }
    public String getName() {
        return name;
    }
    public String getMessage() {
        StringBuilder sb = new StringBuilder();
        sb.append("账户:").append(this.name).append(", ");
        sb.append("金额:").append(amount).append(", ");
        sb.append("日期:").append(date);
        return sb.toString();
    }
}

最后实现事件总线

/**
 * 事件总线
 *
 * @author 湘王
 */
public class EventBusTest {
    // 回调通知
    public static void notifyObserver() {
        EventBus bus = new EventBus();
        AliPayObserver ali = new AliPayObserver();
        WeixinObserver weixin = new WeixinObserver();
        YuePayObserver yue = new YuePayObserver();
        bus.register(ali);
        bus.register(weixin);
        bus.register(yue);
        Account account1 = new Account("ALI", 1.6, new Date());
        bus.post(account1);
        Account account2 = new Account("WEIXIN", 2.2, new Date());
        bus.post(account2);
        Account account3 = new Account("YUE", 3, new Date());
        bus.post(account3);
    }
    public static void main(String[] args) throws InterruptedException {
        notifyObserver();
    }
}

运行main方法,可以看到,尽管没有显式声明观察者接口,但通过一个@Subscribe注解,就完成了方法回调。这就是EventBus比观察者模式要灵活强大的地方。

如果还不满足,那就再来一个例子。

创建观察者接口和具体观察者

/**
 * 做家务的接口
 *
 * @author 湘王
 */
public interface HouseWork {
    public void dry();
}
/**
 * 女主人(具体做家务的人)
 *
 * @author 湘王
 */
public class Woman implements HouseWork {
    @Override
    public void dry() {
        System.out.println("可以晾衣服了");
    }
}

创建Subject:

/**
 * 洗衣机(Subject类)
 *
 * @author 湘王
 */
public class WashingMachine {
    private Vector<HouseWork> vector = new Vector<>();
    public void register(HouseWork work) {
        vector.add(work);
    }
    public void unregister(HouseWork work) {
        vector.remove(work);
    }
    public void notifyObserver() {
        for (HouseWork work : vector) {
            work.dry();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        // 洗衣机
        WashingMachine machine = new WashingMachine();
        // 女主人
        Woman woman = new Woman();
        // 洗衣机让女主人成为自己的观察者
        machine.register(woman);
        System.out.println("将衣服放到洗衣机。。。");
        System.out.println("买菜、遛娃中。。。");
        Thread.sleep(3000);
        // 通知观察者(女主人),衣服洗完了
        machine.notifyObserver();
    }
}

用EventBus把刚才家庭妇女做家务的例子再来做一遍(现在换成家庭妇男):

/**
 * 具体观察者
 *
 * @author 湘王
 */
public class Man {
    @Subscribe
    public void dry(Sheet sheet) {
        System.out.println("可以晾 " + sheet.getName() + " 床单了");
    }
}
/**
 * 事件总线
 *
 * @author 湘王
 */
public class EventBusTest {
    // 回调通知
    public static void notifyObserver() {
        EventBus bus = new EventBus();
        Man man = new Man();
        bus.register(man);
        bus.post(new Sheet("富安娜"));
    }
    public static void main(String[] args) {
        notifyObserver();
    }
}
/**
 * 床单实体类
 *
 * @author 湘王
 */
public class Sheet {
    private String name;
    public Sheet(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

运行main方法,可以看到和之前一样的效果。事件总线的一个缺点是,回调接口必须有参数——这并不友好。

以上就是Java两大工具库Commons和Guava使用示例详解的详细内容,更多关于Java工具库Commons Guava的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java处理表格的实用工具库

    目录 前言 Easy Excel 需求 读取表格 创建对象的读 不创建对象的读 写入表格 EasyExcel特点 总结 前言 处理 Excel 表格是开发中经常遇到的需求,比如表格合并.筛选表格中的某些行列.修改单元格数据等. 今天给大家分享一个 Java 处理表格的工具库,不需要任何专业知识,拿来就能用,快速又轻松~ 可能有同学说了,用 Python 处理表格不是更方便么?为毛用 Java 啊? 当然是因为企业中大部分后台开发用的都是 Java!如果你要搞一个允许用户自主上传 Excel 进行

  • java使用apache commons连接ftp修改ftp文件名失败原因

    今天被ftp上中文名修改坑了好久 项目用的是 apache commons 里的 FtpClient 实现的对ftp文件的上传下载操作,今天增加了业务要修改ftp上的文件名,然后就一直的报错,问题是它修改名字的方法只返回一个boolean,没有异常,这就很蛋疼了,找了好久才发现是中文的名字的原因 改名 直接上代码 package net.codejava.ftp; import java.io.IOException; import org.apache.commons.net.ftp.FTPC

  • Java常用类库Apache Commons工具类说明及使用实例详解

    Apache Commons包含了很多开源的工具,用于解决平时编程经常会遇到的问题,减少重复劳动.下面是我这几年做开发过程中自己用过的工具类做简单介绍. 组件 功能介绍 BeanUtils 提供了对于JavaBean进行各种操作,克隆对象,属性等等. Betwixt XML与Java对象之间相互转换. Codec 处理常用的编码方法的工具类包 例如DES.SHA1.MD5.Base64等. Collections java集合框架操作. Compress java提供文件打包 压缩类库. Con

  • Java项目Guava包 HashMultimap使用及注意事项

    目录 1. 数据模型介绍 2. 简单使用介绍 2.1 容器创建 2.2 添加元素 2.3 移除元素 2.4 替换元素 2.5 获取元素及遍历 2.6 输出所有的key 2.7 输出所有的value 3. 小结 今天给大家介绍一个相对基础的知识点 HashMultmap: guava基本上可以说是java开发项目中,大概率会引入的包,今天介绍的主角是一个特殊的容器 -- HashMultmap,可以简单的将它的数据结构理解为Map<K, Set<V>> 那么为什么会突然想到介绍一下它

  • java的Guava工具包介绍

    集合 普通集合 List<String> list = Lists.newArrayList(); Set<String> set = Sets.newHashSet(); Map<String, String> map = Maps.newHashMap(); Set 取交集.并集.差集 HashSet<Integer> setA = Sets.newHashSet(1, 2, 3, 4, 5); HashSet<Integer> setB =

  • 浅谈Java中GuavaCache返回Null的注意事项

    Guava在实际的Java后端项目中应用的场景还是比较多的,比如限流,缓存,容器操作之类的,有挺多实用的工具类,这里记录一下,在使用GuavaCache,返回null的一个问题 I. 常见使用姿势 @Test public void testGuava() { LoadingCache<String, String> cache = CacheBuilder.newBuilder().build(new CacheLoader<String, String>() { @Overri

  • Java实现大文件的分割与合并的方法详解

    目录 一.题目描述-合并多个文本文件 1.题目 2.解题思路 3.代码详解 二.题目描述-对大文件进行分割处理 1.题目 2.解题思路 3.代码详解 三.题目描述-分割后又再次合并 1.题目 2.解题思路 3.代码详解 4.多学一个知识点 一.题目描述-合并多个文本文件 1.题目 题目:做一个合并多个文本文件的工具. 2.解题思路 创建一个类:TextFileConcatenation 使用TextFileConcatenation继承JFrame构建窗体 读取文本文件时,用的是Buffered

  • java使用Apache工具集实现ftp文件传输代码详解

    本文主要介绍如何使用Apache工具集commons-net提供的ftp工具实现向ftp服务器上传和下载文件. 一.准备 需要引用commons-net-3.5.jar包. 使用maven导入: <dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>3.5</version> </depend

  • java数据结构图论霍夫曼树及其编码示例详解

    目录 霍夫曼树 一.基本介绍 二.霍夫曼树几个重要概念和举例说明  构成霍夫曼树的步骤 霍夫曼编码 一.基本介绍 二.原理剖析 注意: 霍夫曼编码压缩文件注意事项 霍夫曼树 一.基本介绍 二.霍夫曼树几个重要概念和举例说明  构成霍夫曼树的步骤 举例:以arr = {1  3  6  7  8   13   29}  public class HuffmanTree { public static void main(String[] args) { int[] arr = { 13, 7, 8

  • java 与testng利用XML做数据源的数据驱动示例详解

    java 与testng利用XML做数据源的数据驱动示例详解 testng的功能很强大,利用@DataProvider可以做数据驱动,数据源文件可以是EXCEL,XML,YAML,甚至可以是TXT文本.在这以XML为例: 备注:@DataProvider的返回值类型只能是Object[][]与Iterator<Object>[] TestData.xml: <?xml version="1.0" encoding="UTF-8"?> <

  • java开发Dubbo负载均衡与集群容错示例详解

    目录 负载均衡与集群容错 Invoker 服务目录 RegistryDirectory 获取Invoker列表 监听注册中心 刷新Invoker列表 StaticDirectory 服务路由 Cluster FailoverClusterInvoker FailfastClusterInvoker FailsafeClusterInvoker FailbackClusterInvoker ForkingClusterInvoker BroadcastClusterInvoker Abstract

  • Python黑魔法库安装及操作字典示例详解

    目录 1. 安装方法 2. 简单示例 3. 兼容字典的所有操作 4. 设置返回默认值 5. 工厂函数自动创建key 6. 序列化的支持 7. 说说局限性 本篇文章收录于<Python黑魔法手册>v3.0 第七章,手册完整版在线阅读地址:Python黑魔法手册 3.0 文档 字典是 Python 中基础的数据结构之一,字典的使用,可以说是非常的简单粗暴,但即便是这样一个与世无争的数据结构,仍然有很多人 "用不惯它" . 也许你并不觉得,但我相信,你看了这篇文章后,一定会和我一

  • java线程池ThreadPoolExecutor的八种拒绝策略示例详解

    目录 池化设计思想 线程池触发拒绝策略的时机 JDK内置4种线程池拒绝策略 拒绝策略接口定义 AbortPolicy(中止策略) DiscardPolicy(丢弃策略) DiscardOldestPolicy(弃老策略) 第三方实现的拒绝策略 Dubbo 中的线程拒绝策略 Netty 中的线程池拒绝策略 ActiveMQ 中的线程池拒绝策略 PinPoint 中的线程池拒绝策略 谈到 Java 的线程池最熟悉的莫过于 ExecutorService 接口了,jdk1.5 新增的 java.uti

  • Python使用Crypto库实现加密解密的示例详解

    目录 一:crypto库安装 二:python使用crypto 1:crypto的加密解密组件des.py 2:crypto组件使用 知识补充 一:crypto库安装 pycrypto,pycryptodome是crypto第三方库,pycrypto已经停止更新三年了,所以不建议安装这个库:pycryptodome是pycrypto的延伸版本,用法和pycrypto 是一模一样的:所以只需要安装pycryptodome就可以了 pip install pycryptodome 二:python使

  • Java两整数相除向上取整的方式详解(Math.ceil())

    目录 前言: 方式一: 添加三目运算符逻辑代码 方式二:使用ceil函数 方式三:其他逻辑 最后总结 附:java向上取整函数Math.ceil() 前言: Java中两个整数相除,如果不能整除,默认是向下取整的.例如:11 除以 3 的结果是 3.然而,某些情况下(eg. 把11个糖果,每3个分一堆,不足三个也分成一堆,可以分几堆?),我们需要向上取整,这样的情况该如果处理呢? 方式一: 添加三目运算符逻辑代码 x / y + (x % y != 0 ? 1 : 0); 这种方法逻辑上很简单,

  • Java中的魔法类:sun.misc.Unsafe示例详解

    前言 Unsafe类在jdk 源码的多个类中用到,这个类的提供了一些绕开JVM的更底层功能,基于它的实现可以提高效率.但是,它是一把双刃剑:正如它的名字所预示的那样,它是Unsafe的,它所分配的内存需要手动free(不被GC回收).Unsafe类,提供了JNI某些功能的简单替代:确保高效性的同时,使事情变得更简单. 这个类是属于sun.* API中的类,并且它不是J2SE中真正的一部份,因此你可能找不到任何的官方文档,更可悲的是,它也没有比较好的代码文档. 这篇文章主要是以下文章的整理.翻译.

随机推荐