SpringBoot使用ApplicationEvent&Listener完成业务解耦
# 原理
分为项目启动时的事件监听 ,结合
/META-INF/spring.fatories
使用。springboot自带的ApplicationEvent
监听事件,如ApplicationStartedEvent
和应用运行时的事件监听。可以自定义监听事件
# 第一步:定义监听事件,继承ApplicationEvent
# 第二步:定义监听器
定义监听器有三种定义方式:
方式一:利用注解
@EventListener
方式二:利用
ApplicationListener
方式三:利用
SmartApplicationListener
,可以实现多个监听器有顺序地监听
一个事件可以被多个监听器监听;事件监听是无序的,监听到的事件先后顺序完全随机出现的, 要想有序就采用第三种方式
# 第三步:发送监听事件
applicationEventPublisher.publishEvent(new UserRegisterEvent(this,user));
@Service
public class UserService {
@Autowired
ApplicationEventPublisher applicationEventPublisher;
/**
* 用户注册方法
* @param user
*/
public void register(User user)
{
//../省略其他逻辑
//发布UserRegisterEvent事件
applicationEventPublisher.publishEvent(new UserRegisterEvent(this,user));
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 第四步:异步监听
使用异步注解 ,@Aysnc
是Spring内的一个组件,可以完成对类内单个或者多个方法实现异步调用,这样可以大大的节省等待耗时。内部实现机制是线程池任务ThreadPoolTaskExecutor
,通过线程池来对配置@Async的方法或者类做出执行动作。
@Configuration
@EnableAsync
public class ListenerAsyncConfiguration implements AsyncConfigurer {
/**
* 获取异步线程池执行对象
* @return
*/
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//此方法返回可用处理器的虚拟机的最大数量; 不小于1
int core = Runtime.getRuntime().availableProcessors();
//设置核心线程数
executor.setCorePoolSize(core);
//设置最大线程数
executor.setMaxPoolSize(core * 2 + 1);
//除核心线程外的线程存活时间
executor.setKeepAliveSeconds(3);
//如果传入值大于0,底层队列使用的是LinkedBlockingQueue,否则默认使用SynchronousQueue
executor.setQueueCapacity(40);
//线程名称前缀
executor.setThreadNamePrefix("my-executor-");
//设置拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// return new LazyTraceThreadPoolTaskExecutor(beanFactory, executor);
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 事例一:用户注册
@Getter
public class UserRegisterEvent extends ApplicationEvent {
//注册用户对象
private User user;
/**
* 重写构造函数
* @param source 发生事件的对象
* @param user 注册用户对象
*/
public UserRegisterEvent(Object source,User user) {
super(source);
this.user = user;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 第一种方式的监听器
@Component
public class AnnotationRegisterListener {
/**
* 注册监听实现方法
* @param userRegisterEvent 用户注册事件
*/
@EventListener
public void register(UserRegisterEvent userRegisterEvent)
{
//获取注册用户对象
User user = userRegisterEvent.getUser();
//../省略逻辑
//输出注册用户信息
System.out.println("@EventListener注册信息,用户名:"+user.getName()+",密码:"+user.getPassword());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 第二种方式的监听器
@Component
public class RegisterListener implements ApplicationListener<UserRegisterEvent>
{
/**
* 实现监听
* @param userRegisterEvent
*/
@Override
public void onApplicationEvent(UserRegisterEvent userRegisterEvent) {
//获取注册用户对象
User user = userRegisterEvent.getUser();
//../省略逻辑
//输出注册用户信息
System.out.println("注册信息,用户名:"+user.getName()+",密码:"+user.getPassword());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Component
public class RegisterListenerSmartPrint implements SmartApplicationListener {
/**
* 该方法返回true&supportsSourceType同样返回true时,才会调用该监听内的onApplicationEvent方法
* @param eventType 接收到的监听事件类型
* @return boolean
*/
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return eventType == UserRegisterEvent.class;
}
/**
* 该方法返回true&supportsEventType同样返回true时,才会调用该监听内的onApplicationEvent方法
* @param sourceType 接收到的监听事件类型
* @return boolean
*/
@Override
public boolean supportsSourceType(Class<?> sourceType) {
return sourceType == UserService.class;
}
/**
* supportsEventType & supportsSourceType 两个方法返回true时调用该方法执行业务逻辑
* @param event 具体监听实例,这里是UserRegisterEvent
*/
@Override
public void onApplicationEvent(ApplicationEvent event) {
//转换事件类型
UserRegisterEvent userRegisterEvent = (UserRegisterEvent) event;
//获取注册用户对象信息
User user = userRegisterEvent.getUser();
//.../完成注册业务逻辑
System.out.println("注册信息,用户名:"+user.getName()+",密码:"+user.getPassword());
}
/**
* 同步情况下监听执行的顺序
* @return int
*/
@Override
public int getOrder() {
return 0;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@Component
public class RegisterListenerSmartEmail implements SmartApplicationListener {
/**
* 该方法返回true&supportsSourceType同样返回true时,才会调用该监听内的onApplicationEvent方法
* @param eventType 接收到的监听事件类型
* @return boolean
*/
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
// 只有UserRegisterEvent监听类型才会执行下面逻辑
return eventType == UserRegisterEvent.class;
}
/**
* 该方法返回true&supportsEventType同样返回true时,才会调用该监听内的onApplicationEvent方法
* @param sourceType 接收到的监听事件类型
* @return boolean
*/
@Override
public boolean supportsSourceType(Class<?> sourceType) {
// 只有在UserService内发布的UserRegisterEvent事件时才会执行下面逻辑
return sourceType == UserService.class;
}
/**
* supportsEventType & supportsSourceType 两个方法返回true时调用该方法执行业务逻辑
* @param event 具体监听实例,这里是UserRegisterEvent
*/
@Override
@Async
public void onApplicationEvent(ApplicationEvent event) {
try {
//睡3秒钟
Thread.sleep(3000);
}catch (Exception e)
{
e.printStackTrace();
}
//转换事件类型
UserRegisterEvent userRegisterEvent = (UserRegisterEvent) event;
//获取注册用户对象信息
User user = userRegisterEvent.getUser();
System.out.println("用户:"+user.getName()+",注册成功,发送邮件通知。");
}
/**
* 同步情况下监听执行的顺序
* @return int
*/
@Override
public int getOrder() {
return 1;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
参考文档:
SpringBoot使用ApplicationEvent&Listener完成业务解耦 · 语雀 (yuque.com) (opens new window)