文章目录
- 使用示例:
- 原理简析:
前言:ApplicationListener 是spring提供的一个监听器,它可以实现一个简单的发布-订阅功能,用有点外行但最简单通俗的话来解释:监听到主业务在执行到了某个节点之后,在监听器里面做出相应的其它业务变更。下面我们具体看段代码,则能很快的理解:
再次推荐博主原创idea插件: Equals Inspection , 如果经常使用Objects.equals方法,相信这个插件可以有所帮助
(欢迎各位前往idea插件marketplace免费下载)
使用示例:
java代码:
首先定义一个业务实体类,实体类定义字段、get set方法、构造函数
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
/**
* 模拟业务对象实体类
* @author csdn:孟秋与你
*/
public class MyBizEntity {
private String name;
private Integer age;
}
再定义一个事件,事件继承ApplicationEvent
import org.springframework.context.ApplicationEvent;
/**
* 自定义事件(继承ApplicationEvent)
* @author csdn:孟秋与你
*/
public class MyEvent extends ApplicationEvent {
public MyEvent(Object source) {
super(source);
}
public MyEvent() {
// java基础:如果父类只有有参构造 子类需要使用其它构造函数 必须在构造函数第一行调用super 因为子类也是调用父类的构造函数
super(null);
// do other
}
}
定义一个监听器,实现ApplicationListener接口:
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* 监听事件
*/
@Component
public class MyApplicationListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
// 必须判断自己要的类型 因为会监听到所有继承ApplicationEvent的事件
if (applicationEvent instanceof MyEvent) {
Object source = applicationEvent.getSource();
MyBizEntity bizEntity = (MyBizEntity) source;
System.out.println(bizEntity.getName() + ":------------name");
}
}
}
写一个接口进行测试, 此时监听器就能打印输出了
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/test/listener")
@RestController
public class MainBizController {
@Autowired
private ApplicationContext context;
@GetMapping
public String test() {
// do something
// 模拟要传递的业务对象
MyBizEntity bizEntity = new MyBizEntity("name",18);
MyEvent event = new MyEvent(bizEntity);
// 上下文 发布事件
context.publishEvent(event);
return "success";
}
}
原理简析:
为什么发布了事件,监听器就能够监听到呢? 其实原理很简单,就是spring进行了一个朴实无华的直接调用, 我们来看看源码:
context.publishEvent默认是调用AbstractApplicationContext类的publishEvent方法,而publishEvent方法里面调用了SimpleApplicationEventMulticaster 类的multicastEvent方法。
SimpleApplicationEventMulticaster: 首先会获取所有实现了ApplicationListener的监听器 (get by type就可以获取到), 接着会执行 invokeListener方法
我们看看最后doInvokeListener 做了什么:
通过上面源码链路,我们不难发现 其实就是调用了publishEvent方法后,spring在我们不轻易能看到的地方 去调用了一下监听器的onApplicationEvent 方法而已,通过源码我们也可以看到 默认是同步调用(没有定义taskExecutor时), 本质上是一个解耦,把原本可能要写在一起的业务代码拆分了。