本篇文档主要用于介绍 jetlinks 平台下 协议管理中 协议上传以及上传的协议生效的业务和源码流程
1、流程源码解析
1.1、主动触发流程
通过前端页面操作属于主动触发流程。在 “运维管理” ——> “协议管理” 菜单下进行统一管理。通过 新增 ——> 上传jar包——>确认 ,之后一个网络协议就可以使用了。下面来对每一步的操作进行分解
1.1.1、上传jar包并确认流程
当“上传jar包” 完成之后,点击“确认”,请求到 “org.hswebframework.web.crud.web.reactive.ReactiveServiceSaveController#add(reactor.core.publisher.Mono)” 其中 ProtocolSupportController 继承 ReactiveServiceSaveController 。 并最终 执行到 “org.hswebframework.ezorm.rdb.mapping.defaults.DefaultRepository#doInsert(java.util.Collection)”
继续走到 “org.hswebframework.ezorm.rdb.mapping.events.EventResultOperator#create” ,在这个方法里会通过 “tableMetadata.fireEvent” 进行 实体变更消息发布流程
继续进入这个方法,会首先加载系统里的 EventListener ,实际上真正执行业务逻辑的是 EntityEventListener里
进入 EntityEventListener#onEvent() 里,继续走 handleBatchOperation 方法 ,可以看到最终通过 Spring 的 ApplicationEventPublisher组件发布了 一个afterEvent事件
当Spring event事件发布完成之后 ,ProtocolSupportHandler#handleCreated 监听器 方法会被触发
然后通过 reloadProtocol 方法对协议进行重新加载 ,并最终进入到 SpringProtocolSupportLoader#load 方法对协议进行加载
因为上传的是jar包,所以最终的加载会通过 AutoDownloadJarProtocolSupportLoader#load 进行加载
会根据jar包地址 “location -> http://127.0.0.1:5173/api/file/9e9e7fcc9d657829c1bbfad2883a6340?accessKey=4a66c71c3c4a6e93d7690b8dca185456” 转换成本地文件 “.\data\protocols\1823190889886220288_e1cb05f2db466ff3c095b43a603ffdfd.jar” 如果没找到会先通过http的方式进行远程下载到 /data/protocols 目录下 ,然后走父类 JarProtocolSupportLoader#load 再次进行加载
之后通过创建自定义classloader -> ProtocolClassLoader , 通过自定义classloader 加载 协议包里 ProtocolSupportProvider 协议提供者的具体实现 JetLinksProtocolSupportProvider , JetLinksProtocolSupportProvider#create 创建具体的消息协议实体 CompositeProtocolSupport
加载完成之后存储协议
1.2、项目启动重新加载协议流程
1.2.1、通过spring自动配置相应的加载启动类
程序启动时加载配置类 ProtocolAutoConfiguration 中配置信息,配置类中使用Spring框架的ObjectProvider获取 ProtocolSupportLoaderProvider 接口的实现类实例,并将这些实例缓存到SpringProtocolSupportLoader 里的Map集合中,以便后续通过 SpringProtocolSupportLoader 根据不同的协议类型(jar 或者 file )方式进行协议的加载
@Configuration(proxyBeanMethods = false)
@AutoConfigureBefore(DeviceClusterConfiguration.class)
public class ProtocolAutoConfiguration {
// @Bean
// public ProtocolSupportManager protocolSupportManager(ClusterManager clusterManager) {
// return new ClusterProtocolSupportManager(clusterManager);
// }
@Bean
public ServiceContext serviceContext(ApplicationContext applicationContext) {
return new SpringServiceContext(applicationContext);
}
// 这个bean 实现并 CommandLineRunner 会在spring容器启动完成之后执行run触发协议组件的加载
@Bean
public LazyInitManagementProtocolSupports managementProtocolSupports(EventBus eventBus,
ClusterManager clusterManager,
ProtocolSupportLoader loader) {
return new LazyInitManagementProtocolSupports(eventBus, clusterManager, loader);
}
@Bean
@Primary
public LazyProtocolSupports protocolSupports() {
return new LazyProtocolSupports();
}
@Bean
public AutoDownloadJarProtocolSupportLoader autoDownloadJarProtocolSupportLoader(WebClient.Builder builder, FileManager fileManager) {
return new AutoDownloadJarProtocolSupportLoader(builder, fileManager);
}
//自动注入ProtocolSupportLoaderProvider实现到 SpringProtocolSupportLoader中
@Bean
public ProtocolSupportLoader protocolSupportLoader(EventBus eventBus,
ObjectProvider<ProtocolSupportLoaderProvider> providers) {
SpringProtocolSupportLoader loader = new SpringProtocolSupportLoader(eventBus);
providers.forEach(loader::register);
return loader;
}
@Bean
public ProtocolSupports inSpringProtocolSupports(EventBus eventBus,
ObjectProvider<ProtocolSupport> supports) {
StaticProtocolSupports protocolSupports = new StaticProtocolSupports();
for (ProtocolSupport protocol : supports) {
protocolSupports.register(
new RenameProtocolSupport(
protocol.getId(),
protocol.getName(),
protocol.getDescription(),
protocol,
eventBus
)
);
}
return protocolSupports;
}
@Bean
@Profile( "dev" )
public LocalProtocolSupportLoader localProtocolSupportLoader(ServiceContext context) {
return new LocalProtocolSupportLoader(context);
}
}
1.2.2、自动配置加载组件走自动加载协议组件流程
在1.2.1中已经通过 SpringProtocolSupportLoader 收集了系统中所有的协议加载组件包括 AutoDownloadJarProtocolSupportLoader 和 LocalProtocolSupportLoader 。 这些协议加载组件的关系如下
之后由于 LazyInitManagementProtocolSupports 实现 CommandLineRunner , 会执行其 run 方法,run方法会执行其父类 DefaultProtocolSupportManager#init(ProtocolSupportDefinition) , 在方法内会委托 ProtocolSupportLoader (SpringProtocolSupportLoader) #load 走加载协议流程了, 并最终通过
AutoDownloadJarProtocolSupportLoader#load 找到最终的 ProtocolSupportProvider 实现类 JetLinksProtocolSupportProvider (其实是一个协议创建工厂) ,最终通过 JetLinksProtocolSupportProvider#create 创建 ProtocolSupport 实现类 CompositeProtocolSupport
AutoDownloadJarProtocolSupportLoader#load 相关执行流程如下: