@EventListener注解的使用以及工作原理解读(观察者模式)
在开发工作中,会遇到一种场景,做完某一件事情以后,需要广播一些消息或者通知,告诉其他的模块进行一些事件处理,一般来说,可以一个一个发送请求去通知,但是有一种更好的方式,那就是事件监听,事件监听也是设计模式中 发布-订阅模式、观察者模式的一种实现。
观察者模式:简单的来讲就是你在做事情的时候身边有人在盯着你,当你做的某一件事情是旁边观察的人感兴趣的事情的时候,他会根据这个事情做一些其他的事,但是盯着你看的人必须要到你这里来登记,否则你无法通知到他(或者说他没有资格来盯着你做事情)
简介
要想顺利的创建监听器,并起作用,这个过程中需要这样几个角色:
- 事件
(event)
可以封装和传递监听器中要处理的参数,如对象或字符串,并作为监听器中监听的目标。 - 监听器
(listener)
具体根据事件发生的业务处理模块,这里可以接收处理事件中封装的对象或字符串。 - 事件发布者
(publisher)
事件发生的触发者。
ApplicationListener 接口
它是一个泛型接口,泛型的类型必须是ApplicationEvent
及其子类,只要实现了这个接口,那么当容器有相应的事件触发时,就能触发 onApplicationEven
t 方法。ApplicationEvent
类的子类有很多,Spring 框架自带的如下几个。
简单使用
@Component
public class DefinitionApplicationListener implements ApplicationListener<ApplicationEvent> {
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
System.out.println("事件触发:" + applicationEvent.getClass().getName());
}
}
2021-12-31 15:41:01.727 INFO 2076 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8001 (http) with context path ''
事件触发:org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent
事件触发:org.springframework.boot.builder.ParentContextApplicationContextInitializer$ParentContextAvailableEvent
事件触发:org.springframework.boot.context.event.ApplicationPreparedEvent
事件触发:org.springframework.context.event.ContextRefreshedEvent
2021-12-31 15:41:02.105 INFO 2076 --- [ restartedMain] a.s.CloudProvider2Payment8001Application : Started CloudProvider2Payment8001Application in 3.84 seconds (JVM running for 5.469)
事件触发:org.springframework.boot.context.event.ApplicationStartedEvent
事件触发:org.springframework.boot.availability.AvailabilityChangeEvent
事件触发:org.springframework.boot.context.event.ApplicationReadyEvent
事件触发:org.springframework.boot.availability.AvailabilityChangeEvent
=Payment8001Application启动成功=
相当于spring一些自动装配的事件触发会执行这个监听函数
例子实现
实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
private Integer id;
private String name;
}
自定义事件
public class UserEvent extends ApplicationEvent {
//实现父类方法
public UserEvent(Object source) {
super(source);
}
}
自定义监听器
//监听器, 可以接受到 发送的事件
@Component
//方式一:通过@EvnetListener,简单易用,扩展性高
public class UserListener {
//监听器1
@EventListener
public void getUserEvent(UserEvent userEvent) {
System.out.println("getUserEvent-接受到事件(发送短信):" + userEvent);
}
//监听器2
@EventListener
public void getUserEvent2(UserEvent userEvent) {
System.out.println("getUserEvent2-接受到事件(发送邮箱):" + userEvent);
}
}
//方式二:通过实现接口,来定义监听器;不方便扩展
//public class UserListener implements ApplicationListener<UserEvent> {
//
// //只监听UserEvent事件
// @Override
// public void onApplicationEvent(UserEvent userEvent) {
// System.out.println("getUserEvent-接受到事件(发送短信):" + userEvent);
// }
//}
发送事件(业务层Service)
//发送事件
@Service
public class UserService implements ApplicationContextAware, ApplicationEventPublisherAware {
private ApplicationContext applicationContext;
private ApplicationEventPublisher applicationEventPublisher;
//设置应用上下文
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
//设置应用事件发布
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
//新增用户
public String addUser(User user) {
User u = User.builder().id(1).name("xiaoming").build();
//发送事件,事件参数是user (第一种方式)
// applicationContext.publishEvent(new UserEvent(u));
//第二种方式
applicationEventPublisher.publishEvent(new UserEvent(u));
return "发送ok";
}
}
控制层
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("test/event")
public String testEvent() {
return userService.addUser(new User());
}
}
启动springboot项目,验证测试接口
=Payment8001Application启动成功=
2021-12-31 16:48:26.699 INFO 5220 --- [nio-8001-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-12-31 16:48:26.699 INFO 5220 --- [nio-8001-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2021-12-31 16:48:26.704 INFO 5220 --- [nio-8001-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 5 ms
getUserEvent-接受到事件(发送短信):com.atguigu.springcloud.common.eventListener.UserEvent[source=User(id=1, name=xiaoming)]
getUserEvent2-接受到事件(发送邮箱):com.atguigu.springcloud.common.eventListener.UserEvent[source=User(id=1, name=xiaoming)]
网友评论