Spring中使用事件非常简单,只需要以下的几个步骤:
- 1.定义事件,继承ApplicationEvent
- 2.定义监听,要么实现ApplicationListener接口,要么在方法上添加@EventListener注解
- 3.定义发布事件借口,调用ApplicationContext.publishEvent()或者ApplicationEventPublisher.publishEvent();
- 4.业务调用发布事件
业务场景: 注册账号完成之后,需要将账号信息同步到权限平台。
————————————————————————————————————————————————————————————
1.首先定义一个事件(Event)
1.1实际项目:
@Data
public class BaseAsgardEvent<T> extends ApplicationEvent {
private T data;
public BaseAsgardEvent(Object source) {
super(source);
}
public BaseAsgardEvent(Object source,T data){
super(source);
this.data = data;
}
}
1.2参考别人文档:
//自定义事件需要继承ApplicationEvent
public class UserRegisterEvent extends ApplicationEvent {
private String username;
public UserRegisterEvent(Object source, String username) {
super(source);
this.username = username;
}
public String getUsername() {
return username;
}
}
2.定义一个事件监听器(Listener)
2.1 定义事件监听器两种方式
//可以实现ApplicationListener接口监听事件
@Component
@Order(2)//可以使用order指定顺序,越小优先级越高
public class MailUserRegisterListener implements ApplicationListener<UserRegisterEvent> {
@Override
public void onApplicationEvent(UserRegisterEvent event) {
System.out.println(Thread.currentThread().getName()+"-给用户"+event.getUsername()+"发送邮件!");
}
}
//也可以使用@EventListener监听事件
@Component
@Order(1)
public class CouponUserRegisterListener {
@EventListener
public void sendCoupon(UserRegisterEvent event) {
System.out.println(Thread.currentThread().getName()+"-给用户"+event.getUsername()+"发送优惠券!");
}
}
2.2 实际项目:
@Component
@Slf4j
public class AccountEventListener {
@Autowired
UniformAccessClient uniformAccessClient;
@Autowired
AccountMapper accountMapper;
@EventListener
public void merchantBusinessRecordEventListener(BaseAsgardEvent<Account> event) {
Account account = event.getData();
try {
if (account == null) {
return;
}
AccountPO accountPO = accountMapper.selectByPrimaryKey(account.getId());
//调用权限平台服务,同步信息
uniformAccessClient.syncAccountToUniformAccessClient(accountPO);
} catch (Exception e) {
log.error("商户档案变更,同步发送消息失败", e);
}
}
}
3.发布事件方法,这里包装ApplicationContext方法使用
@Component
public class SpringContextHolder implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
/**
* 获取静态变量中的ApplicationContext.
*/
public static ApplicationContext getApplicationContext() {
assertContextInjected();
return applicationContext;
}
/**
* 从静态变量applicationContext中得到Bean, 自动转型为所赋值对象的类型.
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
assertContextInjected();
return (T) applicationContext.getBean(name);
}
/**
* 从静态变量applicationContext中得到Bean, 自动转型为所赋值对象的类型.
*/
public static <T> T getBean(Class<T> requiredType) {
assertContextInjected();
return applicationContext.getBean(requiredType);
}
/**
* 清除SpringContextHolder中的ApplicationContext为Null.
*/
public static void clearHolder() {
applicationContext = null;
}
/**
* 实现ApplicationContextAware接口, 注入Context到静态变量中.
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
SpringContextHolder.applicationContext = applicationContext;
}
/**
* 检查ApplicationContext不为空.
*/
private static void assertContextInjected() {
Validate.validState(applicationContext != null,
"applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder.");
}
//包装方法
public static void publish(Object event) {
applicationContext.publishEvent(event);
}
}
4.实际使用:
@Service
public class TestMethod {
public void store(Account account) {
//处理账号业务。。。。。。。。。。。
//处理其他业务完成。。。。。。。。。。。
//商户账号 同步
BaseAsgardEvent<Account> event = new BaseAsgardEvent<Account>("ACCOUNT", account);
SpringContextHolder.publish(event);
}
}