项目中很多场景可以使用事件来对系统进行解耦,让系统更便于维护和扩展。SpringBoot项目默认是支持事件的,我们只需要自定义事件,然后发布事件,之后监听事件处理业务逻辑即可。SpringBoot中我们会用到事件抽象类ApplicaltionEvent,事件监听接口ApplicationListener,事件发布接口ApplicationEventPublisher或ApplicationContextAware。
事件发布无论是用ApplicationEventPublisher还是ApplicationContextAware都可以,实际上都是调用了publishEvent(ApplicationEvent event)方法进行事件发布。
从Springboot源码来看,ApplicationContextAware 接口定义了一个set方法,用于注入ApplicationContext 对象,而ApplicationContext继承ApplicationEventPublisher接口。
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext var1) throws BeansException;
}
@FunctionalInterface
public interface ApplicationEventPublisher {
default void publishEvent(ApplicationEvent event) {
this.publishEvent((Object)event);
}
void publishEvent(Object var1);
}
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
@Nullable
String getId();
String getApplicationName();
String getDisplayName();
long getStartupDate();
@Nullable
ApplicationContext getParent();
AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}
使用示例如下:
1.定义一个事件,事件需要继承ApplicationEvent,否则无法发布。
package com.xmc.event;
import org.springframework.context.ApplicationEvent;
import java.util.Map;
/**
* 定义一个事件
*/
public class SmsEvent extends ApplicationEvent {
// 事件参数
private Map<String, String> map;
public SmsEvent(Object source, Map<String,String> map) {
super(source);
this.map = map;
}
public Map<String,String> getParam() {
return map;
}
}
2.编写Service层代码,用于事件发布。
以下分别是通过注入ApplicationEventPublisher 对象和实现ApplicationContextAware接口通过setter方式注入ApplicationContext对象的方式,来调用publishEvent方法发布事件。
@Service
public class SmsService {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
/**
* 发布事件
* @param smsEvent
*/
public void SendSms(SmsEvent smsEvent) {
applicationEventPublisher.publishEvent(smsEvent);
}
}
package com.xmc.service;
import com.xmc.event.SmsEvent;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
@Service
public class SmsService2 implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* 发布事件
* @param smsEvent
*/
public void SendSms(SmsEvent smsEvent) {
applicationContext.publishEvent(smsEvent);
}
}
3.编写controller层代码
package com.xmc.controller;
import com.xmc.event.SmsEvent;
import com.xmc.service.SmsService;
import com.xmc.service.SmsService2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
public class UserRegisterController {
@Autowired
private SmsService smsService;
@Autowired
private SmsService2 SmsService2;
@GetMapping("/registerUser")
public String registerUser() {
Map<String,String> map = new HashMap<>();
map.put("phone", "12345678901");
SmsEvent smsEvent = new SmsEvent(this, map);
smsService.SendSms(smsEvent);
return "注册成功";
}
@GetMapping("/registerUser2")
public String registerUser2() {
Map<String,String> map = new HashMap<>();
map.put("phone", "12345678902");
SmsEvent smsEvent = new SmsEvent(this, map);
SmsService2.SendSms(smsEvent);
return "注册成功2";
}
}
4.编写listener监听器,用监听器来执行发送短信任务。一般来说实现了ApplicationListener接口后,要把事件类型作为泛型传入。如果不传入事件类型的泛型, 则重写onApplicationEvent方法后就是public void onApplicationEvent(ApplicationEvent event), 需要通过event.getSource()拿到关心的类型再做处理。
package com.xmc.listener;
import com.xmc.event.SmsEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* 事件监听器
*/
@Component
public class SmsListener implements ApplicationListener<SmsEvent> {
@Override
public void onApplicationEvent(SmsEvent smsEvent) {
System.out.println("正在向手机号:" + smsEvent.getParam().get("phone") + "发送短信");
}
}
测试结果:
正在向手机号:12345678901发送短信
正在向手机号:12345678902发送短信
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)