- 作者:老汪软件技巧
- 发表时间:2024-10-30 17:02
- 浏览量:
Nop平台核心引擎的实现代码都很简短,一般模块的核心代码量都是5000行左右的量级,只有ORM比较复杂一些,1万多行。虽然代码很短,实际实现的功能特性却很多,要把所有细节设计都介绍到,文档量还是不小。建议有问题可以先查看源码,核心特性都有单元测试支持,可以通过调试单元测试来学习源码(直接在关键类中加断点,然后沿着堆栈向上看)。
Nop平台所有的设计都非常简单直接,一般核心代码集中在少数几个类中。
一. 可逆计算核心原理ResourceComponentManager平台统一的DSL模型加载入口DefaultVirtualFileSystem自动扫描classpath下所有_vfs目录中的文件,构成一个虚拟文件系统,并自动识别delta定制路径ResourceLoadingCache根据虚拟文件路径缓存解析结果ResourceDependsManager跟踪模型解析过程中发现的模型文件依赖关系,实现方式类似vue组件的动态依赖追踪,当文件被修改时,自动使得所有依赖该文件的解析结果失效DslModelParser根据XDef元模型配置,使用DslBeanModelParser将XML解析为DSL模型对象DslNodeLoader和XDslExtender在DslModelParser内部使用,加载资源文件,执行可逆计算理论中的x-extends算法,动态合成XNode节点对象DeltaMerger和DeltaDiffer实现可逆计算理论中的x-extends算法和x-diff算法DslModelToXNodeTransformer根据XDef元模型,将DSL模型对象转换为XNode节点二. NopXLangXLangXLang语言编译器的使用入口XplCompilerXML格式的Xpl模板语言的编译器XLangParseTreeParser/XLangASTBuildVisitor根据antlr自动生成的XScript脚本语言解析器,并自动将Antlr的ParseTree转换为XLangAST抽象语法树节点XplLibTagCompilerXpl模板语言中的标签库编译器SimpleExprParser简单的嵌入表达式的解析器,不支持函数定义和复杂语句LexicalScopeAnalysis对抽象语法树进行词法作用域分析,并执行宏函数BuildExecutableProcessor将抽象语法树节点转换为可执行的IExecutableExpression可执行解释函数接口XDefinitionParserXDef元模型解析器DslNodeLoader解析XML文件,执行差量合并,合成得到最终的XNodeXDslValidator根据XDef元模型,验证XNode的合法性DslModelParser根据XDef元模型,解析XNode得到DSL模型对象ObjMetaToXDef/XDefToObjMeta实现XDefinition元模型和ObjMeta元数据模型之间的相互转换DslModelToXNodeTransformer将DSL模型对象反向序列化为XNodeDslXNodeToJsonTransformer根据XDef元模型,将DSL对应的XNode节点转换为JSON对象CompactXNodeToJsonTransformer/CompactJsonToXNodeTransformer在没有XDef元模型的情况下,通过约定type和body等少量属性,实现紧凑格式的XNode与JSON之间的相互转换三. NopCodeGenXCodeGenerator代码生成器的核心入口CodeGenTaskmvn install时通过exec-maven-plugin插件调用的代码生成器入口CliGenCommandnop-cli命令行工具调用代码生成器的入口函数,内部使用XCodeGenerator实现AstGrammarBuilder分析g4语法定义,转换为AstGrammar模型结构。
根据ParseTree自动构造AST语法树时会使用AstGrammar所提供的信息JdkJavaCompilerAOP代码生成时使用JDK内置的java编译器来编译Java文件为字节码JavaObjMetaParser利用janino解析器,将后缀名为xjava的文件解析为ObjMeta对象。EqlAST和XLangAST等生成抽象语法树结构时都使用了这一机制。四. NopIoCBeanContainerImpl外部访问IoC容器的核心接口,负责管理所有的beanAppBeanContainerLoader执行bean的自动发现功能。扫描所有模块下的autoconfig bean,以及满足beans/app-*.beans.xml模式的bean文件BeanContainerBuilder根据收集到的所有bean配置,构建BeanContainer对象BeanConditionEvaluator检查ioc:condition等动态条件,处理alias映射,剔除所有不满足条件的beanBeanDefinitionBuilder处理@Inject注解等自动编配属性,初始化所有property的valueResolverAopBeanProcessor将bean的创建类替换为Aop增强后的派生类,并注入interceptor配置ConfigExpressionProcessor识别bean属性配置中的@cfg:nop.server.port和${nop.server.port}这种配置表达式,将它们转换为IValueResolver五. NopConfigDefaultConfigProvider外部使用配置管理引擎的核心入口ConfigStarter配置管理引擎的核心逻辑,在这里详细定义了配置项加载顺序和覆盖关系RouterConfigSource实现灰度配置发布NacosConfigService基于Nacos实现从远程配置中心获取配置,并实现配置实时更新六. NopDaoDaoProvider外部使用的获取IEntityDao的统一入口DialectManager统一管理数据库方言模型JdbcTemplateImpl类似于Spring中的JdbcTemplate,对JDBC访问请求的模板模式封装。
内置数据缓存和多数据源支持JdbcTransactionFactory对数据库事务的封装,支持柔性事务和异步处理JdbcDataSet通用的DataSet结构封装,凡是表格类型的数据全部封装为统一的IDataSet接口七. NopORMOrmSessionImplORM引擎的核心功能入口,负责所有实体状态切换和一级缓存管理OrmSessionEntityCache一级缓存的实现。从数据库中获取的所有数据都存放在一级缓存中。OrmEntity实体对象的基类,记录实体和属性的修改状态EntityPersisterImpl单实体对象的增删改查处理,识别全局缓存和多租户,内部使用EntityPersisterDriver来最终访问外部存储CollectionPersisterImpl一对多集合对象的增删改查处理,识别全局缓存和多租户JdbcEntityPersistDriver单实体对象的JDBC持久化实现JdbcCollectionPersistDriver一对多集合对象的JDBC持久化实现OrmBatchLoadQueue批量加载优化,解决JPA长期存在的N+1问题JdbcQueryExecutor利用EqlCompiler将EQL对象查询语法转换为SQL语句并执行EqlCompiler将EQL语法编译为SQL语句,使用EqlTransformVisitor将对象属性关联转换为表关联,AstToSqlGenerator根据转换后的AST语法树生成SQL语句CascadeFlushersession.flush的时候会递归检查所有实体是否被修改,并自动生成对应的增删改查操作,放入BatchActionQueue执行队列,后者最终会调用EntityPersisterOrmTemplate类似于Spring中HibernateTemplate的模板模式封装EntityDao在OrmTemplate的基础上,针对单个实体类的封装,功能类似于JpaRepository的加强版。
一般业务开发中优先使用这个接口SqlLibManager类似MyBatis的EQL和SQL语句管理器。SqlLibInvoker负责将Mapper接口方法调用转化为对SqlLibManager方法的调用八. NopGraphQLGraphQLEngine外部使用的GraphQL引擎核心入口GraphQLDocumentParser手工编写的GraphQL语言解析器GraphQLSelectionResolver验证前端发过来的GraphQL查询语句中的元素都具有合法定义RpcSelectionSetBuilderREST调用模式下,如果前端不传送@selection参数,则这里自动添加所有非lazy的字段作为selectionGraphQLExecutor任务派发和结果选择的具体执行逻辑BizObjectManager使用BizObjectBuilder动态组装BizObject业务对象。将BizObjet上的方法映射为GraphQLOperation,将BizObject的属性结构映射为GraphQLObjectDefinition。BizObjectBuilder将XMeta文件、XBiz文件中的信息,以及BizModel Java类中的信息合成在一起,构成有一个完整的BizObject业务对象。
ReflectionBizModelBuilder和ReflectionGraphQLTypeFactory使用反射机制,根据Java类上的@BizModel/@BizQuery等注解构造GraphQL操作定义和类型定义ObjMetaToGraphQLDefinition将xmeta元数据定义转换为GraphQL类型定义BizModelToGraphQLDefinition将xbiz模型定义转换为GraphQL操作定义GraphQLActionAuthChecker精确到字段级别的权限约束九. NopRPCClusterRpcClient分布式RPC客户端调用的核心逻辑ClusterRpcProxyFactoryBean/RpcInvocationHandler将RPC接口适配到ClusterRpcClient对象上的方法HttpRpcService基于http协议实现RPC调用MessageRpcClient基于单向发送和接收的消息队列实现RPC调用SentinelFlowControlRunner集成Sentinel实现熔断限流LoadBalanceServerChooser通过负载均衡算法选择服务实例RouteServiceInstanceFilter识别消息头中的nop-svc-route配置,实现服务的灰度发布十. NopGrpcGrpcServer启动gRPC服务器,将GraphQL服务转换为gRPC服务对外暴露GraphQLServerCallHandler将gRPC的服务端处理器转换为对GraphQLEngine的调用ServiceSchemaManager根据GraphQL类型定义,动态生成protobuf格式的编解码器GraphQLToApiModel将GraphQL服务定义转换为api.xdef元模型定义的Api模型十一. NopReportReportEngine外部访问报表引擎的核心入口ExcelWorkbookParser将xlsx文件解析为ExcelWorkbook对象,直接解析xlsx文件中的XML,不使用Apache POI包。
ExcelToXptModelTransformer将ExcelWorkbook转换为报表模型对象,XptModelInitializer分析XptModel中父子单元格的关联关系,产生的分析结果保存在XptCellModel中ExcelFormulaParser解析Excel公式语法,将它转换为ReportExprReportExpressionParser为普通的表达式引擎增加报表层次坐标语法支持ExpandedSheetGenerator执行报表引擎的核心逻辑,将ExcelSheet模板动态展开为ExpandedSheet,内部使用TableExpander实现表格展开TableExpander/CellRowExpander/CellColExpander执行中国式报表的行列对称展开算法,构造ExpandedTable对象DynamicReportDataSet在报表展开过程中,提供数据集封装,简化层次坐标和数据集数据转换操作CellCoordinateHelper层次坐标表达式的核心执行逻辑ExcelTemplate将展开后的ExpandedSheet导出为Excel文件,直接生成xml和xlsx文件,不使用POI库HtmlTemplate将展开后的ExpandedSheet导出为Html文件WordTemplate基于docx格式的Word模板生成Word文件,可以在Word中进行可视化编辑十二. NopRuleRuleManager外部使用规则引擎的核心入口ExecutableRule和ExecutableMatrixRule决策树和决策矩阵的具体执行逻辑RuleExprParser手工编写的类似于FEEL(Friendly Enough Expression Language)的表达式语法解析器DaoRuleModelLoader和DaoRuleModelSaver将规则模型保存到nop_rule_definition表中RuleExcelModelParser从xlsx文件中解析规则模型,支持决策树和决策矩阵RuleServiceImpl将规则引擎功能对外暴露为GraphQL和REST服务十三. NopWorkflowWorkflowManagerImpl外部访问工作流引擎的核心入口WorkflowImpl从WorkflowManager中创建或者加载的工作流对象,它内部调用WorkflowEngine实现功能WorkflowEngineImpl工作流引擎的核心实现逻辑DaoWorkflowStore工作流的持久化存储WfModelAnalyzer分析工作流模型配置的有效性,并剔除回退分支,构建出DAG有向无环图模型DaoWfActorResolver适配外部用户、角色、部门管理和工作委托机制WorkflowServiceImpl提供对外的GraphQL服务和REST服务十四. NopBatchBatchTaskBuilder负责创建BatchTask的工厂类。
它负责组织skip/retry/transaction/process/listener的处理顺序BatchTask批处理任务的核心逻辑,多线程并行执行,每个线程上分批次执行,每次处理一个chunkRetryBatchConsumer为chunk处理增加失败重试逻辑BatchProcessorConsumer逐条处理输入数据,并收集所有的输出数据到列表结构中,然后统一调用一次下游的consumerPartitionDispatchLoader根据业务数据特征,将数据派发到不同的数据分区队列中进行处理ResourceRecordLoader通用的数据文件加载器ResourceRecordConsumer通用的数据文件输出机制BatchGenLoader压力测试中使用的测试数据生成器,根据配置动态生成具有指定数据分布的测试数据十五. NopJobDefaultJobScheduler外部使用Job调度引擎的核心入口TriggerBuilder定时触发器的构造逻辑CalendarBuilderCalendar表达需要被的假期和指定时间区间TriggerExecutorImplJob定时调度的核心执行逻辑十六. NopAutoTestJunitAutoTestCase需要录制回放支持的单元测试从这个基类继承。
注解中标注的NopJunitExtension提供了具体的与Junit集成支持JunitBaseTestCase不需要录制回放功能,但是需要使用NopIoC注入bean的单元测试从这个基类继承BaseTestCase最简单的,不需要NopIoC自动注入的测试用例可以从这个基类继承,它提供给了获取资源文件数据的一些便捷方法AutoTestCaseDataBaseInitializer根据input目录下录制的数据自动初始化内存数据库AutoTestCaseDataSaver将通过AutoTestOrmHook收集到的对数据库修改的内容保存到output目录下AutoTestCaseResultChecker单元测试执行完之后,自动运行checker来检查执行结果与录制的数据内容是否匹配AutoTestMatchChecker使用nop-match模块提供的前缀引导匹配语法来校验数据模式AutoTestVars单元测试运行过程中产生的随机数等每次运行都变化的量需要在这个集合中注册,这样在录制的时候会把它们替换为变量名