1、自定义事件
1.1、为什么要使用自定义事件
为了业务解耦
首先要了解几个概念
- 事件源:事件的触发者,发布事件(一般是广播)
- 事件
- 事件监听器:用于消费事件
比如一个注册业务,可能包含三个动作:注册、发送邮件提醒用户注册成功、发送优惠券,如果将这三个动作放在一个方法里执行,那耦合度就很大,如果发送邮件或发送优惠券等次要业务失败,会导致注册也跟着失败,这显然是灾难性的
如果利用事件机制,可以把用户注册当成一个事件,而发送邮件和发送优惠券当成两个监听器,用来监听用户注册事件,则可以避免以上问题
1.2、自定义事件实战
1.2.1、定义事件
import org.springframework.context.ApplicationEvent;
public class UserRegisterEvent extends ApplicationEvent {
private String username;
public UserRegisterEvent(Object source) {
super(source);
}
public UserRegisterEvent(Object source,String username) {
super(source);
this.username = username;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
1.2.2、定义监听器(接口方式)
import com.asiainfo.com.springboottest.event.UserRegisterEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
@Order(1)
public class SendMailListener implements ApplicationListener<UserRegisterEvent> {
@Override
public void onApplicationEvent(UserRegisterEvent userRegisterEvent) {
System.out.println("给用户["+userRegisterEvent.getUsername()+"]发送邮件成功!");
}
}
1.2.3、定义监听器(注解方式)
import com.asiainfo.com.springboottest.event.UserRegisterEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
public class UserRegisterListener {
@EventListener
@Order(2)
public void sendMailListener(UserRegisterEvent userRegisterEvent) {
System.out.println("给用户["+userRegisterEvent.getUsername()+"]发送邮件成功!");
}
@EventListener
@Order(3)
public void sendCouponsListener(UserRegisterEvent userRegisterEvent) {
System.out.println("给用户["+userRegisterEvent.getUsername()+"]发送优惠券成功!");
}
}
1.2.4、service层
import com.asiainfo.com.springboottest.annotation.PrintAccess;
import com.asiainfo.com.springboottest.annotation.RecordLog;
import com.asiainfo.com.springboottest.event.UserRegisterEvent;
import com.asiainfo.com.springboottest.service.IUserService;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import java.util.Date;
@Service
public class UserServiceImpl implements IUserService, ApplicationEventPublisherAware {
private ApplicationEventPublisher applicationEventPublisher;
@Override
public void registerUser(String username) {
System.out.println("用户["+username+"]注册成功!");
//发布用户注册事件,事件源根据实际业务传参,不影响程序运行
this.applicationEventPublisher.publishEvent(new UserRegisterEvent(applicationEventPublisher,username));
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
}
1.2.5、支持异步
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.scheduling.concurrent.ThreadPoolExecutorFactoryBean;
import java.util.concurrent.Executor;
@Configuration
public class AsyncEventListenerConfig {
@Bean
public ApplicationEventMulticaster applicationEventMulticaster() {
//创建一个事件广播器,spring内部默认用的也是SimpleApplicationEventMulticaster这个广播器
SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
//给广播器提供一个线程池,通过这个线程池来调用事件监听器
Executor executor = this.applicationEventMulticasterThreadPool().getObject();
//设置异步执行器
multicaster.setTaskExecutor(executor);
return multicaster;
}
@Bean
public ThreadPoolExecutorFactoryBean applicationEventMulticasterThreadPool() {
ThreadPoolExecutorFactoryBean threadPoolExecutorFactory = new ThreadPoolExecutorFactoryBean();
threadPoolExecutorFactory.setThreadNamePrefix("applicationEventMulticasterThreadPool-");
threadPoolExecutorFactory.setCorePoolSize(5);
return threadPoolExecutorFactory;
}
}
2、spring自带事件
import com.asiainfo.com.springboottest.event.UserRegisterEvent;
import org.springframework.context.event.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
public class InnerEventListener {
@EventListener
public void contextRefreshedEventListener(ContextRefreshedEvent contextRefreshedEvent) {
System.out.println("spring上下文刷新了!");
}
@EventListener
public void contextStartedEventListener(ContextStartedEvent contextStartedEvent) {
System.out.println("spring上下文开启了!");
}
@EventListener
public void contextStoppedEventListener(ContextStoppedEvent contextStoppedEvent) {
System.out.println("spring上下文停止了!");
}
@EventListener
public void contextClosedEventListener(ContextClosedEvent ContextClosedEvent) {
System.out.println("spring上下文关闭了!");
}
}