Apollo数据同步源码分析
本文基于
shenyu-2.6.1版本进行源码分析,官网的介绍请参考 数据同步原理 。
Admin管理端
以新增插件的流程来理解下整体的流程

接收数据
- PluginController.createPlugin()
进入PluginController类中的createPlugin()方法,它负责数据的校验,添加或更新数据,返回结果信息。
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/plugin")
public class PluginController {
@PostMapping("")
@RequiresPermissions("system:plugin:add")
public ShenyuAdminResult createPlugin(@Valid @ModelAttribute final PluginDTO pluginDTO) {
// 调用pluginService.createOrUpdate 进行处理逻辑
return ShenyuAdminResult.success(pluginService.createOrUpdate(pluginDTO));
}
// ......
}
处理数据
- PluginServiceImpl.createOrUpdate() -> PluginServiceImpl.create()
在PluginServiceImpl类中通过create()方法完成数据的转换,保存到数据库,发布事件。
@RequiredArgsConstructor
@Service
public class PluginServiceImpl implements SelectorService {
// 事件发布对象 pluginEventPublisher
private final PluginEventPublisher pluginEventPublisher;
private String create(final PluginDTO pluginDTO) {
// 判断有没有对应的插件
Assert.isNull(pluginMapper.nameExisted(pluginDTO.getName()), AdminConstants.PLUGIN_NAME_IS_EXIST);
// 自定义的插件jar
if (!Objects.isNull(pluginDTO.getFile())) {
Assert.isTrue(checkFile(Base64.decode(pluginDTO.getFile())), AdminConstants.THE_PLUGIN_JAR_FILE_IS_NOT_CORRECT_OR_EXCEEDS_16_MB);
}
// 创建plugin对象
PluginDO pluginDO = PluginDO.buildPluginDO(pluginDTO);
// 插入对象到数据库
if (pluginMapper.insertSelective(pluginDO) > 0) {
// 插件新增成功,则发布创建事件
// publish create event. init plugin data
pluginEventPublisher.onCreated(pluginDO);
}
return ShenyuResultMessage.CREATE_SUCCESS;
}
// ......
}
在PluginServiceImpl类完成数据的持久化操作,即保存数据到数据库,并通过 pluginEventPublisher 进行发布事件。
pluginEventPublisher.onCreateed方法的逻辑是:发布变更的事件。
@Override
public void onCreated(final PluginDO plugin) {
// 发布DataChangeEvent事件:事件分组(插件、选择器、规则)、事件类型(创建、删除、更新)、变更的数据
publisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.PLUGIN, DataEventTypeEnum.CREATE,
Collections.singletonList(PluginTransfer.INSTANCE.mapToData(plugin))));
// 发布PluginCreatedEvent
publish(new PluginCreatedEvent(plugin, SessionUtil.visitorName()));
}
发布变更数据通过publisher.publishEvent()完成,这个publisher对象是一个ApplicationEventPublisher类,这个类的全限定名是org.springframework.context.ApplicationEventPublisher。看到这儿,我们知道了发布数据是通过Spring相关的功能来完成的。
关于
ApplicationEventPublisher:当有状态发生变化时,发布者调用
ApplicationEventPublisher的publishEvent方法发布一个事件,Spring容器广播事件给所有观察者,调用观察者的onApplicationEvent方法把事件对象传递给观察者。调用publishEvent方法有两种途径,一种是实现接口由容器注入ApplicationEventPublisher对象然后调用其方法,另一种是直接调用容器的方法,两种方法发布事件没有太大区别。
ApplicationEventPublisher:发布事件;ApplicationEvent:Spring事件,记录事件源、时间和数据;ApplicationListener:事件监听者,观察者;
在Spring的事件发布机制中,有三个对象,
一个是发布事件的ApplicationEventPublisher,在ShenYu中通过构造器注入了一个eventPublisher。
另一个对象是ApplicationEvent,在ShenYu中通过DataChangedEvent继承了它,表示事件对象。
public class DataChangedEvent extends ApplicationEvent {
//......
}
最后一个是 ApplicationListener,在ShenYu