事件抛发

一、事件侦听和抛发
必须先侦听后抛发

document.addEventListener("自定义事件",anhaoHandler);

// new Event()指创建一个事件对象
var  evt=new Event("自定义事件");
evt.a=10;
// 向document抛发新建的event事件
document.dispatchEvent(evt);

function anhaoHandler(e){
    console.log(e===evt);//打印结果true
    console.log(e.a);//打印结果10
}

作用1:解耦合

// 高耦合
// 烂代码
var obj1={
    a:function(){
        obj2.d(5);
    },
    b:function(sum){
        console.log(sum)
    }
}

var obj2={
    c:function(){
        obj1.b(10);
    },
    d:function(s){
        console.log(s);
    }
}

// 对象间的数据传递
obj1.a();//5
obj2.c();//10
// 解耦
var obj1={
    a:function(){
        // this  对象的方法中this就是该对象自身,这里this就是obj1
        document.addEventListener("aaa",this.b);
    },
    b:function(e){
        // 传到这里
        console.log(e.s);
    }
}

var obj2={
    v:10,
    c:function(){
        var s=5;
        var evt=new Event("aaa");
        evt.s=s;
        document.dispatchEvent(evt);
    },
    d:function(){

    }

}

// 打算执行obj2.c 将局部变量5传递给obj1的方法b中

obj1.a();
obj2.c();//打印结果5

二、jQuery中的事件抛发

$(document).on('abc',a,function(e,obj){
      console.log(e,a,obj);
     });
$(document).trigger('abc',{a:1,b:[1,2,3]});

jQuery中没有dipatchEvent方法
trigger抛发事件,类似于dipatchEvent
事件抛发过程中是可以传参的
(原生事件中事件本身是不能有第二个参数的,
但在jq中可以有第二个参数)
如果传参是数组,事件接收函数中从第二位参数向后对应数组的每个元素
如果传参使用的是对象或者其他数据,事件接收函数中只有第二位参数可以接收
不支持事件抛发时多个数据直接传参,也就是说trigger函数只有两个参数,第一个是事件类型,第二个是要传的参数

事件传参有两个
1、事件触发前传参,侦听时传入的参数
2、事件触发时传参,抛发事件时传入的参数

abc();
function abc(){
   var a=1;
  //  这个a就是事件触发前传参
   $(document).on("abc",a,abcHandler);
   $(document).on("click",clickHandler);
}

function abcHandler(e,b,c){
  // console.log(e.data),这个就是事件触发前传参的a
  // console.log(b,c);这个b和c就是抛发事件时传参b和c
  console.log(e.data);
  console.log(b,c);
}

function clickHandler(){
   var b=3;
   var c=5;
  $(document).trigger("abc",[b,c])
}

三、nodejs中的events内置模块

const events = require('events');

// events模块是一个类

class MyEvent extends events {}

let ev = new MyEvent();

ev.on('sayHi', function() { // 监听事件
    console.log('hi');
});

ev.emit('sayHi'); // 用于触发事件

eventEmitter.emit() 方法可以传任意数量的参数到监听器函数。 当监听器函数被调用时, this 关键词会被指向监听器所绑定的 EventEmitter 实例。

const events=require('events');

// console.log(events);//是一个类
class MyEvent extends events{};//继承
let evt=new MyEvent();//实例化对象

evt.on('sayhi',function(a,b){//监听事件
    console.log(a,b,this);
    /* aaa bbb MyEvent {
        _events: [Object: null prototype] { sayhi: [Function] },
        _eventsCount: 1,
        _maxListeners: undefined,
        [Symbol(kCapture)]: false
    } */
});

evt.emit('sayhi','aaa','bbb');
Spring Boot 提供了基于观察者模式的事件驱动机制,允许开者在系统中布和监听自定义或内置的**应用事件(Application Events)**。这些事件可以用于解耦业务逻辑,例如在应用启动完成之后执行某些初始化任务,或者在生异常时触通知。 --- ### 🌟 Spring Boot 常见系统事件 Spring Boot 内置了一些重要的 `ApplicationEvent`,主要由 `ApplicationContext` 布: | 事件类 | 触时机 | |--------|---------| | `ApplicationStartingEvent` | 应用开始启动,但在任何处理之前(除了注册监听器和初始化器) | | `ApplicationEnvironmentPreparedEvent` | 环境准备就绪,但上下文尚未创建 | | `ApplicationContextInitializedEvent` | 上下文已准备好,但尚未加载任何 bean | | `ApplicationPreparedEvent` | Bean 定义加载完成,但尚未刷新上下文 | | `ApplicationReadyEvent` | 应用已准备好处理请求(启动完成) | | `ApplicationFailedEvent` | 启动过程中出现异常 | 此外还可以自定义事件。 --- ## ✅ 示例:监听 Spring Boot 系统事件 ### 1. 使用 `@EventListener` 监听内置事件 ```java import org.springframework.boot.context.event.*; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; @Component public class SystemEventListener { @EventListener public void onApplicationStart(ApplicationStartingEvent event) { System.out.println("👉 应用正在启动..."); } @EventListener public void onEnvironmentPrepared(ApplicationEnvironmentPreparedEvent event) { System.out.println("👉 环境已经准备就绪"); } @EventListener public void onContextInitialized(ApplicationContextInitializedEvent event) { System.out.println("👉 应用上下文已初始化"); } @EventListener public void onApplicationPrepared(ApplicationPreparedEvent event) { System.out.println("👉 应用已准备,Bean 定义加载完毕"); } @EventListener public void onApplicationReady(ApplicationReadyEvent event) { System.out.println("✅ 应用启动完成,可以开始处理请求!"); } @EventListener public void onApplicationFailed(ApplicationFailedEvent event) { System.err.println("💥 应用启动失败: " + event.getException().getMessage()); } } ``` > 这些监听器会自动注册并响应对应阶段的事件。 --- ### 2. 自定义事件 & 布/监听 #### (1) 创建自定义事件类 ```java import org.springframework.context.ApplicationEvent; public class UserRegisteredEvent extends ApplicationEvent { private String username; public UserRegisteredEvent(Object source, String username) { super(source); this.username = username; } public String getUsername() { return username; } } ``` #### (2) 事件的服务类 ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; @Service public class UserService { @Autowired private ApplicationEventPublisher eventPublisher; public void registerUser(String username) { System.out.println("👤 正在注册用户: " + username); // 模拟注册逻辑... // 事件 eventPublisher.publishEvent(new UserRegisteredEvent(this, username)); } } ``` #### (3) 监听自定义事件 ```java import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; @Component public class UserRegistrationListener { @EventListener public void handleUserRegistration(UserRegisteredEvent event) { System.out.println("📬 用户注册成功,送欢迎邮件给: " + event.getUsername()); // 可以在这里调用邮件服务等 } } ``` > 如果希望异步处理(如邮件不阻塞主流程),可结合 `@Async` 使用(需启用异步支持)。 #### (4) 启用异步支持(可选) ```java import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; @Configuration @EnableAsync public class AsyncConfig { } ``` 然后修改监听方法: ```java @EventListener @Async public void handleUserRegistration(UserRegisteredEvent event) { try { Thread.sleep(2000); // 模拟耗时操作 System.out.println("📧 异步送欢迎邮件给: " + event.getUsername()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } ``` --- ## 🔍 工作原理说明 - Spring 的事件机制基于 **观察者设计模式**。 - 所有事件通过 `ApplicationEventPublisher` 布。 - 使用 `@EventListener` 注解的方法会被自动注册为监听器。 - 默认情况下,事件是**同步执行**的;若要异步,使用 `@Async`。 - 也可以通过实现 `ApplicationListener<T>` 接口来监听事件。 示例接口方式: ```java @Component public class ReadyListener implements ApplicationListener<ApplicationReadyEvent> { @Override public void onApplicationEvent(ApplicationReadyEvent event) { System.out.println("🔔 应用已就绪(通过接口实现)"); } } ``` --- ## ⚠️ 注意事项 1. **线程模型**:默认所有监听器与布者在同一线程中运行,可能影响性能。 2. **异常传播**:如果监听器出异常,默认会中断后续监听器执行。 3. **条件监听**:可以用 SpEL 表达式控制是否触: ```java @EventListener(condition = "#event.username.startsWith('admin')") ``` 4. **事务绑定事件**:可通过 `@TransactionalEventListener` 在事务提交后触动作(比如仅当事务成功才消息)。 --- ### ✅ 典型应用场景 - 应用启动完成后初始化缓存、定时任务、连接外部系统。 - 用户注册后送邮件/SMS/记录日志。 - 错误生时告警通知。 - 微服务间低耦合通信(配合消息队列更佳)。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值