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

 更新时间:2023年02月07日 16:39:46   作者:湘王  
这篇文章主要为大家介绍了Java两大工具库Commons和Guava使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

正文

除了操作集合、限流和缓存,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的资料请关注脚本之家其它相关文章!

相关文章

  • Java如何基于IO流实现同一文件读写操作

    Java如何基于IO流实现同一文件读写操作

    这篇文章主要介绍了Java如何基于IO流实现文件读写操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • Java实现双向循环链表

    Java实现双向循环链表

    这篇文章主要为大家详细介绍了Java实现双向循环链表,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-10-10
  • SpringBoot动态导出word文档实整教程(复制即可使用)

    SpringBoot动态导出word文档实整教程(复制即可使用)

    在我们做项目的时候会需要把数据库中的数据导出到word当中,下面这篇文章主要给大家介绍了关于SpringBoot动态导出word文档实整教程的相关资料,文中的代码复制即可使用,需要的朋友可以参考下
    2023-06-06
  • 在java中获取List集合中最大的日期时间操作

    在java中获取List集合中最大的日期时间操作

    这篇文章主要介绍了在java中获取List集合中最大的日期时间操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • RabbitMQ 在 Spring Boot 项目中的深度应用与实战解析

    RabbitMQ 在 Spring Boot 项目中的深度应用与实战解析

    RabbitMQ 作为一款广受欢迎的开源消息队列系统,遵循 AMQP 协议,能够在分布式系统里实现应用程序之间的异步通信、解耦以及流量削峰等关键功能,这篇文章主要介绍了RabbitMQ 在 Spring Boot 项目中的深度应用与实战解析,需要的朋友可以参考下
    2025-01-01
  • Spring Security密码解析器PasswordEncoder自定义登录逻辑

    Spring Security密码解析器PasswordEncoder自定义登录逻辑

    这篇文章主要为大家介绍了Spring Security密码解析器PasswordEncoder自定义登录逻辑示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • 微信公众号服务号推送模板消息设置方法(后端java)

    微信公众号服务号推送模板消息设置方法(后端java)

    公众号时经常会需要写推送消息,从网上找了一大堆,都不是很全,所以这篇文章主要介绍了微信公众号服务号推送模板消息设置方法的相关资料,需要的朋友可以参考下
    2023-02-02
  • SpringBoot之Profile的两种使用方式详解

    SpringBoot之Profile的两种使用方式详解

    当在不同的环境下,想通过修改配置文件来连接不同的数据库,比如在开发过程中启动项目时,想连接开发环境对应的数据库,可以在配置文件中指定environment=dev,其他环境类似,此时就需要用到Spring为我们提供的Profile功能,本文给大家介绍了SpringBoot之Profile的两种使用方式
    2024-10-10
  • java利用htmlparser获取html中想要的代码具体实现

    java利用htmlparser获取html中想要的代码具体实现

    这篇文章主要介绍了java利用htmlparser获取html中想要的代码具体实现,需要的朋友可以参考下
    2014-02-02
  • Java序列化常见的三个问题

    Java序列化常见的三个问题

    这篇文章主要介绍了Java序列化常见的三个问题,帮助大家更好的理解和学习JAVA,感兴趣的朋友可以了解下
    2020-08-08

最新评论