阅读spring boot如何执行事件监听器的代码,就意识到事件监听机制应该在spring boot中运用很广,而且它的代码形式就是要让开发者来使用的。所以就去搜索了下具体在Spring boot中运行事件监听器要怎么做。
因为阅读代码的过程中,spring boot内置的事件监听器已经教会我怎么在spring boot里添加事件监听器,发布事件,执行对应动作这一个流程了,所以就想看看还有没有其他的知识点。果然还是有的。
首先,一个完整的事件监听过程涉及到四个对象:
1、发送事件的主体
2、事件的类型定义
3、发布事件的发布器
4、事件的监听器
如下示例主要来自这篇《Spring Boot 事件和监听》
先来定义一个简单的事件:
package com.shahuwang.bootsample.listener;
import org.springframework.context.ApplicationEvent;
public class BlackListEvent extends ApplicationEvent {
private String address;
public BlackListEvent(Object source, String address){
super(source);
this.address = address;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
再来定义一个简单的事件监听器:
package com.shahuwang.bootsample.listener;
import org.springframework.context.ApplicationListener;
public class BlackListListener implements ApplicationListener<BlackListEvent> {
@Override
public void onApplicationEvent(BlackListEvent blackListEvent) {
String threaid = Thread.currentThread().getName();
System.out.println(threaid + "收到了黑名单事件:" + blackListEvent.getAddress());
}
}
然后把监听器注册到spring boot里面:
package com.shahuwang.bootsample;
import com.shahuwang.bootsample.listener.BlackListListener;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication
public class BootsampleApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(BootsampleApplication.class);
app.addListeners(new BlackListListener());
app.run(args);
}
}
此时,只要在其他地方发布这个事件,马上就会执行对应的代码了。这个事件要怎么发布呢?
如下是一段简单的接口代码,在里面发布了事件:
package com.shahuwang.bootsample.service;
import com.shahuwang.bootsample.listener.BlackListEvent;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.atomic.AtomicLong;
@RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@Autowired
private ApplicationContext context;
@GetMapping("/greeting")
public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
BlackListEvent event = new BlackListEvent(this, "greeting");
context.publishEvent(event);
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
}
package com.shahuwang.bootsample.service;
public class Greeting {
private final long id;
private final String content;
public Greeting(long id, String content) {
this.id = id;
this.content = content;
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
}
此时,只要把整个项目运行起来,然后访问:http://localhost:8080/greeting 就能看到console打出【收到了黑名单事件】几个字了。
如上的方式定义一个事件监听器还是复杂了点,而且需要写好多个类。Spring boot还支持某个类的方法成为监听器,如下即是:
package com.shahuwang.bootsample.listener;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;
@Component
public class AnnotationListener {
@EventListener
public void processBlacklistEvent(BlackListEvent event){
String threaid = Thread.currentThread().getName();
System.out.println("annotation listener------------------" + threaid);
}
}
通过加上@Component 和 @EventListener 两个注解,就可以让一个方法成为监听器。
阅读代码的过程中,我看到spring boot的事件执行有两种方式,一种是在主线程里面顺序执行,一种是新起一个线程来执行,似乎是通过读取某个配置来区分。后来搜索到需要加上@Async 这个注解,然而我加上了也没有用,再后来发现还需要在主类上加上@EnableAsync这个注解。
代码如下:
package com.shahuwang.bootsample.listener;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;
@Component
public class AnnotationListener {
@EventListener
@Async
public void processBlacklistEvent(BlackListEvent event){
String threaid = Thread.currentThread().getName();
System.out.println("annotation listener------------------" + threaid);
}
}
package com.shahuwang.bootsample;
import com.shahuwang.bootsample.listener.BlackListListener;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication
@EnableAsync
public class BootsampleApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(BootsampleApplication.class);
app.addListeners(new BlackListListener());
app.run(args);
}
}
这样子每次事件到来都是新起一个线程来执行了。
除了上述两种方式注册监听器,还可以通过properties文件里面配置监听器,由spring boot在启动的时候加载。
首先,在src/resources下的application.properties(如果没有就创建一个)加上这么一行:
context.listener.classes=\
com.shahuwang.bootsample.listener.BlackListListener
这个BackListListener 就会在启动的时候,由org.springframework.boot.context.config.DelegatingApplicationListener
加载并注册到spring boot里面了。如果有多个监听器,可以这样写:
context.listener.classes=\
com.shahuwang.bootsample.listener.BlackListListener,\
com.shahuwang.bootsample.listener.BlackListListener2
DelegatingApplicationListener 由spring boot初始化时启动,然后监听ApplicationEnvironmentPreparedEvent事件,收到事件后,就找当前项目的properties文件,并加载里面context.listener.classes对应的监听器
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。