今天写代码的时候遇到了监听器,然后我就鬼使神差的翻了一下Spring框架文档,看到了自定义监听事件,下面是我的收获分享。
spring中自带有5种标准事件,ContextRefreshedEvent,ContextStartedEvent,ContextStoppedEvent,ContextClosedEvent,RequestHandledEvent。需要了解的话,可自行网上搜索或者看官方文档。
流程:
首先继承ApplicationEvent类,创建我们的自定义事件。
public class MyApplicationEvent extends ApplicationEvent{
private static final long serialVersionUID = -543396148689229096L;
private final String address;
public final String test;
public MyApplicationEvent(Object source ,String address ,String test) {
super(source);
this.address = address;
this.test = test;
}
@Override
public String toString() {
return "MyApplicationEvent [address=" + address + ", test=" + test + "]";
}
// accessor and other methods...
}
想要发布我们的自定义事件,就需要调用ApplicationEventPublisher类中的publishEvent()方法 。官方文档中是叫我们创建一个实现ApplicationEventPublisherAware的类,并且注册为spring中的bean。
@Component
public class MyApplicationEventService implements ApplicationEventPublisherAware{
private List blackList;
private ApplicationEventPublisher publisher;
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
public void sendEmail(String address, String text) {
blackList = new ArrayList<>();
blackList.add("[email protected]");
blackList.add("[email protected]");
blackList.add("[email protected]");
if (blackList.contains(address)) {
publisher.publishEvent(new MyApplicationEvent(this, address, text));
return;
}
// send email...
}
public void testListener(String address, String text) {
MyApplicationEvent event = new MyApplicationEvent(this, address, text);
publisher.publishEvent(event);
}
}
在配置的时候,Spring容器会检测到这个MyApplicationEventService实现 ApplicationEventPublisherAware并自动调用 setApplicationEventPublisher()。实际上,传入的参数将是Spring容器本身; 您只需通过其ApplicationEventPublisher接口与应用程序上下文进行 交互。
完成发布,就要写事件监听器,创建一个实现 ApplicationListener的类,并且注册为spring中的bean。
@Component
public class MyApplicationListener implements ApplicationListener<MyApplicationEvent>{
public void onApplicationEvent(MyApplicationEvent event) {
System.out.println("my listener start");
System.out.println(event.toString());
System.out.println("my listener end");
}
}
onApplicationEvent中编写你的监听逻辑。
总的实现效果就是,你一使用MyApplicationEventService类的sendEmail()和testListener()方法,监听器就会触发。写一个controller来测试一下效果。
@RestController
@RequestMapping("/listener")
public class ListenerController {
@Autowired
private MyApplicationEventService myApplicationEventService;
@GetMapping("/listener")
public String testMyListener() {
/*myApplicationEventService.sendEmail("[email protected]", "123123"); */
myApplicationEventService.testListener("[email protected]", "123");
return "SUCCESS";
}
}
使用浏览器访问http://127.0.0.1:8080/listener/listener,打出日志中有
my listener start
MyApplicationEvent [address=john.doe@example.org, test=123]
my listener end
这说明我们的自定义事件和监听器起作用了。
@Component
public class MyTestListener {
@EventListener
public void testListenr(MyApplicationEvent event) {
System.out.println("my listener start");
System.out.println(event.toString());
System.out.println("my listener end");
}
}
MyTestListener 类实现的效果和MyApplicationListener 类一样。
使用注解还有两好处
1 . 你可以在一个注解中监听多种事件
@EventListener({ContextRefreshedEvent.class, MyApplicationEvent .class})
public void testListenr() {
System.out.println("my listener start");
System.out.println("my listener end");
}
2 . 还可以通过condition注释的属性添加额外的运行时过滤,该过滤器定义一个SpEL表达式。
@EventListener(condition="#event.test == '123'")
public void testListenr(MyApplicationEvent event) {
System.out.println("my listener start");
System.out.println(event.toString());
System.out.println("my listener end");
}