# enet **Repository Path**: xnat/enet ## Basic Information - **Project Name**: enet - **Description**: 小清新响应式事件驱动工具 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 30 - **Forks**: 7 - **Created**: 2019-01-14 - **Last Updated**: 2024-12-19 ## Categories & Tags **Categories**: utils **Tags**: 事件驱动, 事件, 异步事件, 事件总线 ## README # 介绍 响应式事件驱动工具 ep.fire("event1", "参数1", "参数2") 工具包含三个组件: EL(事件监听), EP(事件中心), EC(事件执行上下文) # 安装教程 ```xml cn.xnatural enet 1.1.2 ``` # 事件驱动库原理 ![Image text](http://www.plantuml.com/plantuml/png/XP91Im91583lyoiUTb5I8RsfXHTlHe6_ODoPrOrrDsOdMJ2XeWA9K46Zi4Edwj1148JgxpYJ_Ojcjy5i5RmDxttplJVlJT7ZcF6JXeqC6tiUb0wXXG2sMgP5RTA6VNnSg71cERKab2sFKuUoFR0z5SyhRhlLeBpkAj2q68t_aZ3xk9bzJaNlDWa7rIDgy7GwBReNSZXEv54R8SVb56ngSd1DLJ6N2trA9pjdyh7pDUgBtfjuU9NtJs9ygUBYQZ8_7nHBPNdtBYT3H1q2WKIhc5MhBrn18mXq3_ENPz7jB_7gVONJL0egb3Kfsu4SoC7qUtIzg1aXCXk9x1f23rCN2IUgceyxk45X5s8Onn8gr7Gj0XZ7WtE4g5R_2DzNHFk_CmERfP6yxuTvlQ9rqkogr32MBnd6gfQGWD1x1a92RL4DNFsf7m00) 1. 事件监听器 ```java // 定义监听 public class TestEP { // 用@EL注解标记一个方法为事件监听 @EL(name = "hello") void hello() { System.out.println("hello world"); } } ``` 2. 事件中心 ```java // 方法1: 创建一个事件中心 final EP ep = new EP(); ``` ```java // 方法2: 创建一个事件中心 final EP ep = new EP(Executors.newFixedThreadPool(2, new ThreadFactory() { final AtomicInteger i = new AtomicInteger(); @Override public Thread newThread(Runnable r) { return new Thread(r, "ep-" + i.incrementAndGet()); } })); ``` 3. 注册事件 ```java // 会解析对象中所有包含@EL方法 ep.addListenerSource(new TestEP()); ``` 4. 触发事件 ```java ep.fire("hello"); // 打印: hello world ``` # 其他用法 ## 带参数事件 ```java @EL(name = "event1") void hello(String p1, Integer p2) { System.out.println("p1: " + p1 + ", p2"); } // 传参 ep.fire("event1", "参数1", 2); // 默认填充参数为null ep.fire("event1"); ``` ## 有返回的事件 ```java @EL(name = "event1") String event1(String p1) { return p1;} // 触发 Object value = ep.fire("event1", "xxx"); ``` ## 多返回值 ```java new EP().addListenerSource(new Object() { @EL(name = "e1") String m1() { return "p1"; } }).addListenerSource(new Object() { @EL(name = "e1") String m11() { return "p11"; } }).fire("e1", ec -> { Assertions.assertTrue(ec.results().stream().map(o -> (String) o).collect(Collectors.joining("")).equals("p1p11")); }); ``` ## 事件执行完回调 ```java ep.fire("hello", (ec) -> { // 事件结束执行 }, "参数1"); ep.fire("hello", (ec) -> { if (ec.isSuccess()) { // 事件成功结束后执行 } }, "参数1"); ``` ## 动态监听器 ```java //1. 添加监听 ep.listen("dynEvent1", () -> { System.out.println("执行动态事件: 无参"); }); //2. 添加带参数的监听 ep.listen("dynEvent2", (p) -> { System.out.println("执行动态事件: 入参: " + p); return p; }); ep.fire("dynEvent1"); System.out.println(ep.fire("dynEvent2", "3333")); ``` ## 动态事件名 ```java @EL(name = "{xx}.hello") void xxhello() { System.out.println("xx hello"); } String getXx() { return "aa"; } // ep.fire("aa.hello") ``` ## 删除事件监听 ```java // 删除某个事件的监听 ep.removeEvent("dynEvent1"); ``` ```java // 移除对象源的所有监听器 ep.removeSourceAllEvent(source); ``` ## 同步异步 ### 同步执行(默认) ```java // 1. 监听器设置同步(默认就是同步) @EL(name = "sync", async = false) String syncListener(){ return "xxx";} ``` ```java // 2. 强制同步执行 Object result = ep.fireSync("sync"); ``` ### 异步执行 ```java // 1. 监听器设置异步 @EL(name = "async", async = true) String asyncListener(){ return "oo"; } ``` ``` // 2. 强制异步执行 ep.fireAsync("async"); ``` ```java // 3. 接收异步结果 ep.fireAsync("async", ec -> { // 异步结果: ec.result }); ``` ## 执行顺序 > 同相事件名的多个监听器的执行顺序: 由@EL order 指定(默认: 0) >> 从小到大执行, 越小越先执行 > + 先按优先级顺序执行所有同步监听器 > + 再按优先级分组执行所有异步监听器 ```java @EL(name = "order") void order1() {log.info("同步 order1");} @EL(name = "order", async = true) void order2() {log.info("异步 order2");} @EL(name = "order", async = true) void order22() {log.info("异步 order22");} @EL(name = "order", async = true) void order222() {log.info("异步 order222");} @EL(name = "order", async = true, order = 1f) void order3() {log.info("异步 order3");} ``` > 所以会先执行 order1, 结束后再并发执行(order2,order22,order22), 结束后再执行 order3 ## 执行次数限制 ```java @EL(name = "once", limit = 1, async = true) void once() { log.info("只执行一次"); } ``` ```java ep.fire("once", ec -> { log.info("once: success: " + ec.isSuccess() + ", isNoListener: " + ec.isNoListener()); }); ep.fire("once", ec -> { log.info("once: success: " + ec.isSuccess() + ", isNoListener: " + ec.isNoListener()); }); ``` ## debug模式 日志打印事件执行前后详情 ```java // 方法1 ep.fireDebug("hello", "参数1"); ``` ```java // 方法2 ep.addTrackEvent("hello"); ``` ## 事件执行上下文 ```java @EL(name = "ec") String ec(EC ec, String p1) { return p1 + ec.getAttr("key1"); } // 每次触发一个事件 都会有一个 EC 对象(事件执行上下文) ep.fire("ec"); // 自动创建EC对象 ep.fire(new EC("ec").args("xx").attr("key1", "oo")); // 手动创建EC对象,并设置属性. 返回: xxoo ``` ## 自定临时义监听器 ```java new EP().fire(new EC("xxx"), new Listener.RunnableListener(() -> { log.info("========RunnableListener"); }) { @Override protected void doInvoke(EC ec, BiConsumer resultAcceptor) { super.doInvoke(ec, resultAcceptor); // 可异步触发 log.info("=========doInvoke"); } }); ``` # [远程事件](https://gitee.com/xnat/remoter) # TODO - [ ] 是否同事件名支持多个重载方法? # 参与贡献 xnatural@msn.cn