4.可以动态地增加或删除发布者和订阅者,扩展性较好。
interface Subscriber { void update(String message); }2.创建发布者,用于发布消息。实现了增加、删除和发布的功能,并且维护了一个订阅列表,
class Publisher { // 堆代码 duidaima.com private Map<String, List<Subscriber>> subscribers = new HashMap<>(); public void subscribe(String topic, Subscriber subscriber) { List<Subscriber> subscriberList = subscribers.get(topic); if (subscriberList == null) { subscriberList = new ArrayList<>(); subscribers.put(topic, subscriberList); } subscriberList.add(subscriber); } public void unsubscribe(String topic, Subscriber subscriber) { List<Subscriber> subscriberList = subscribers.get(topic); if (subscriberList != null) { subscriberList.remove(subscriber); } } public void publish(String topic, String message) { List<Subscriber> subscriberList = subscribers.get(topic); if (subscriberList != null) { for (Subscriber subscriber : subscriberList) { subscriber.update(message); } } } }3.我们还实现了两个不同的 Subscriber 实现,一个是 EmailSubscriber,另一个是 SMSSubscriber,用于接受发布者的消息并将其分别发送到邮箱和手机上。
class EmailSubscriber implements Subscriber { private String email; public EmailSubscriber(String email) { this.email = email; } public void update(String message) { System.out.println("Send email to " + email + ": " + message); } } class SMSSubscriber implements Subscriber { private String phoneNumber; public SMSSubscriber(String phoneNumber) { this.phoneNumber = phoneNumber; } public void update(String message) { System.out.println("Send SMS to " + phoneNumber + ": " + message); } }4.在 Main 类中,我们创建了一个 Publisher 对象,并添加了两个 EmailSubscriber 和两个 SMSSubscriber,分别订阅了 news 主题的更新。我们先给这个主题发送一条消息,然后取消 news 主题的其中一个订阅者,最后我们再次给 news 主题发送一条消息。
public class Main { public static void main(String[] args) { Publisher publisher = new Publisher(); Subscriber emailSubscriber1 = new EmailSubscriber("foo@example.com"); Subscriber smsSubscriber1 = new SMSSubscriber("1234567890"); publisher.subscribe("news", emailSubscriber1); publisher.subscribe("news", smsSubscriber1); publisher.publish("news", "发布新消息1"); publisher.unsubscribe("news", smsSubscriber1); publisher.publish("news", "发布新消息2"); } }打印输出如下:
Send email to foo@example.com: 发布新消息1 Send SMS to 1234567890: 发布新消息1 Send email to foo@example.com: 发布新消息2
public class OrderEvent extends ApplicationEvent { void onApplicationEvent(Object event) { ... } }2.定义订单监听器,实现 ApplicationListener
@Component public class OrderListener implements ApplicationListener<OrderEvent> { @Override public void onApplicationEvent(OrderEvent event) { // 生成订单、删除购物车、扣减库存 ... } }3.下单流程,通过事件发布器 applicationEventPublisher 发布订单事件,然后再订单监听器中处理订单保存逻辑。
@Resource private ApplicationEventPublisher applicationEventPublisher; private void saveOrder(MallUserVO mallUserVO, Long couponUserId, List<ShopCatVO> shopcatVOList, String orderNo) { // 订单检查 ... // 生成订单号 String orderNo = NumberUtil.genOrderNo(); // 发布订单事件,在事件监听中处理下单逻辑 applicationEventPublisher.publishEvent(new OrderEvent(orderNo, mallUserVO, couponUserId, shopcatVOList)); // 所有操作成功后,将订单号返回 return orderNo; ... }通过事件监听机制,我们将下单逻辑拆分成如下步骤:
/** * 堆代码 duidaima.com * 系统启动时執行 */ @Component public class SpringBeanStartupRunner implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { // 设置spring默认的事件监听为异步执行 SimpleApplicationEventMulticaster multicaster = SpringContextUtil.getBean(SimpleApplicationEventMulticaster.class); ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 5, 10, 60L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(500), new CustomizableThreadFactory("newbee—event-task"), new ThreadPoolExecutor.CallerRunsPolicy() ); multicaster.setTaskExecutor(threadPoolExecutor); } }在系统启动时反射修改SimpleApplicationEventMulticaster类的taskExecutor属性,从而让SimpleApplicationEventMulticaster类支持异步事件通知。