使用Spring事件监听机制实现跨模块调用

最近一个项目,有两个模块,A模块需要依赖B模块,但现在B模块有地方需要调用A模块的方法,如果直接依赖,又会产生循环依赖问题。最终选择使用spring的事件监听来解决该问题。

思路就是,B模块去发布事件,A中监听,得到数据后,通过引用返回给B。

首先是定义事件

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
public class getUserInfoEvent extends ApplicationEvent {
private String message;
private Integer griddingId;
private StringBuilder griddingName;

public getUserInfoEvent(Object source, String message, Integer griddingId, StringBuilder griddingName) {
super(source);
this.message = message;
this.griddingId = griddingId;
this.griddingName = griddingName;//接收要获取到值的StringBuilder
}

public StringBuilder getGriddingName() {
return griddingName;
}

public Integer getGriddingId() {
return griddingId;
}

public String getMessage() {
return message;
}
}

然后在B中去发布事件

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
   @Autowired
ApplicationEventPublisher applicationEventPublisher; //这个必须注入

@Override
public SysUserVO getUserInfo(Long userId) {
SysUser user = getById(userId);

Integer griddingId = user.getGriddingId();
StringBuilder griddingName= new StringBuilder(); //使用stringbuilder进行引用字符串操作,来获取需要的值
//上面是业务相关


getUserInfoEvent event = new getUserInfoEvent(this,"发布“获取用户信息”事件",griddingId,griddingName); //定义事件
applicationEventPublisher.publishEvent(event); //发布事件


//下面是获取到数据之后的操作,不重要
//这里事件是同步进行的

SysUserVO sysUserVO = new SysUserVO();
BeanUtils.copyProperties(user,sysUserVO);

sysUserVO.setGriddingName(griddingName.toString());

// 找到该用户所属角色
String roleName = getRoleByUserId(userId);
sysUserVO.setRoleName(roleName);

SysUser parentUser = sysUserMapper.selectById(user.getParentId());
sysUserVO.setParentName(ObjectUtils.isEmpty(parentUser) ? null : parentUser.getUserName());

return sysUserVO;
}

最后在A中监听事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@EventListener
public void getGriddingNameByUserIdEventListener(getUserInfoEvent event) { //参数必须填写要监听的事件类,事件发布后这边就会监听到
//形参event中存有传递的相关数据
System.out.println(event.getMessage()); //会打印出---发布“获取用户信息”事件

//下面为个人业务相关代码
Integer griddingId = event.getGriddingId();
StringBuilder griddingName = event.getGriddingName();

//再通过网格id来查找对应的网格信息
GriddingArea griddingArea = getOne(new LambdaQueryWrapper<GriddingArea>().eq(GriddingArea::getId, griddingId));

griddingName.append(griddingArea.getGriddingName()); //使用同一个StringBuilder对象来操作,这里把获取到的字符串存入后,事件发布者那边就能得到数据了。

System.out.println("griddingName"+griddingName);
}

非常好用👍