ASP.NET Boilerplate 插件(PlugIn)开发实战:以 DatabaseMaintainer 插件定时清理审计日志

发布时间:2026/9/23 22:50:15

ASP.NET Boilerplate 插件(PlugIn)开发实战:以 DatabaseMaintainer 插件定时清理审计日志 后端Web框架依赖注入认证鉴权【免费下载链接】aspnetboilerplateASP.NET Boilerplate - Web Application Framework项目地址https://gitcode.com/gh_mirrors/as/aspnetboilerplate点击查看免费下载本篇技术指南以 ASP.NET BoilerplateABP框架的插件机制为核心完整演示如何从零创建一个名为DatabaseMaintainer的插件类库通过继承AbpModule定义插件模块、借助PeriodicBackgroundWorkerBase实现定时清理审计日志的后台工作器并将其动态加载进 ASP.NET Core 应用Startup.cs中通过PlugInSources.AddFolder挂载。读完本文你将掌握 ABP 插件项目的搭建、构建产物部署、运行时装载原理以及仓库源码中IPlugInSource系列实现背后的加载与装配机制可直接复用到日志清理、定时任务、模块化扩展等真实场景。插件机制概览ABP 如何发现并加载一个插件ABP 的插件PlugIn本质上是独立的程序集 继承AbpModule的模块类。应用启动时ABP 会扫描插件来源PlugIn Source把插件程序集里的模块类型当作普通模块一样纳入模块依赖图统一经历PreInitialize→Initialize→PostInitialize生命周期模块生命周期详见 Module-System.md。从源码结构看这套机制由src/Abp/PlugIns/目录下的类型协作完成类型职责IPlugInSource插件来源抽象暴露GetAssemblies()与GetModules()两个方法IPlugInSource.csFolderPlugInSource扫描指定文件夹下的 DLL/EXE 程序集FolderPlugInSource.csAssemblyFileListPlugInSource直接按文件路径列表加载程序集AssemblyFileListPlugInSource.csPlugInTypeListSource直接以模块Type列表声明插件PlugInTypeListSource.csPlugInSourceList插件来源集合聚合去重所有程序集与模块PlugInSourceList.csAbpPlugInManager持有PlugInSources集合并注册AppDomain.AssemblyResolve兜底解析AbpPlugInManager.cs运行时装配链可以概括为应用在ConfigureServices中通过services.AddAbpTStartupModule(options ...)传入options.PlugInSources扩展方法见 AbpServiceCollectionExtensions.csAbpBootstrapperOptions.PlugInSources定义见 AbpBootstrapperOptions.cs。AbpBootstrapper.Initialize()把options.PlugInSources合并进AbpPlugInManager.PlugInSourcesAbpBootstrapper.cs。AbpModuleManager.Initialize递归查找依赖模块后调用_abpPlugInManager.PlugInSources.GetAllModules()收集插件模块类型并标记为插件模块参与创建与启动AbpModuleManager.cs。其中什么类型算一个 ABP 模块由AbpModule.IsAbpModule(Type)判定必须是非抽象、非泛型、继承AbpModule的类AbpModule.cs。FolderPlugInSource在GetModules()中正是用这个方法逐个类型过滤FolderPlugInSource.cs。创建插件搭建 DatabaseMaintainer 类库项目新建类库并引入必要 NuGet 包在 IDE 中新建一个类库Class Library项目例如名为DatabaseMaintainer注意本插件需要引用Abp与Abp.ZeroCore两个 NuGet 包。Abp.ZeroCore提供模块零Module Zero的多租户、审计日志等基础设施其AbpZeroCoreModule定义见 AbpZeroCoreModule.cs因为我们要操作的是 Module Zero 的AuditLog实体。编写插件模块类插件必须有一个继承AbpModule的模块类并用[DependsOn]声明它依赖AbpZeroCoreModule这样模块零的实体映射、工作单元、审计基础设施都会随插件一并加载using System.Reflection; using Abp.Modules; using Abp.Threading.BackgroundWorkers; using Abp.Zero; namespace DatabaseMaintainer { [DependsOn(typeof(AbpZeroCoreModule))] public class DatabaseMaintainerModule : AbpModule { public override void Initialize() { // 按约定注册当前程序集中的所有类应用服务、仓储、工作器等 IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly()); } public override void PostInitialize() { // 应用启动完成后把后台工作器注册进全局后台工作器管理器 var workManager IocManager.ResolveIBackgroundWorkerManager(); workManager.Add(IocManager.ResolveDeleteOldAuditLogsWorker()); } } }两个重写方法的分工Initialize()通过IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly())按 ABP 约定注册程序集中的类型单例、瞬态、ISingletonDependency等这是让后台工作器可被IocManager.Resolve的前提。PostInitialize()在所有模块初始化完成、应用即将对外服务时把工作器加入IBackgroundWorkerManager。这正是 ABP 官方模块自身的惯用模式——AbpZeroCoreModule也是在PostInitialize中把UserTokenExpirationWorker注册进工作器管理器AbpZeroCoreModule.cs我们的插件模块与之一致。BackgroundWorkerManager的Add方法会记录工作器若管理器已在运行状态则立即Start()BackgroundWorkerManager.cs。编写后台工作器DeleteOldAuditLogsWorker插件要完成的核心业务是在给定周期内删除审计日志。这里采用PeriodicBackgroundWorkerBase——一个内置周期计时器的后台工作器基类周期计时器细节见 Background-Jobs-And-Workers.mdusing System; using Abp.Auditing; using Abp.Dependency; using Abp.Domain.Repositories; using Abp.Domain.Uow; using Abp.Threading.BackgroundWorkers; using Abp.Threading.Timers; using Abp.Timing; namespace DatabaseMaintainer { public class DeleteOldAuditLogsWorker : PeriodicBackgroundWorkerBase, ISingletonDependency { private readonly IRepositoryAuditLog, long _auditLogRepository; public DeleteOldAuditLogsWorker(AbpTimer timer, IRepositoryAuditLog, long auditLogRepository) : base(timer) { _auditLogRepository auditLogRepository; Timer.Period 5000; // 周期单位毫秒这里即每 5 秒执行一次 } [UnitOfWork] protected override void DoWork() { Logger.Info(---------------- DeleteOldAuditLogsWorker is working ----------------); using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.MayHaveTenant)) { var fiveMinutesAgo Clock.Now.Subtract(TimeSpan.FromMinutes(5)); _auditLogRepository.Delete(log log.ExecutionTime fiveMinutesAgo); CurrentUnitOfWork.SaveChanges(); } } } }要点逐项拆解基类与依赖注入PeriodicBackgroundWorkerBase在构造时订阅AbpTimer.Elapsed事件Start()启动计时器、每次触发调用抽象方法DoWork()异常会被捕获并记录为Logger.WarnPeriodicBackgroundWorkerBase.cs。AbpTimer.Period以毫秒为单位默认不立即触发RunOnStart默认falseAbpTimer.cs。声明ISingletonDependency使工作器在插件程序集中按约定注册为单例可被模块PostInitialize安全地Resolve出来。仓库注入IRepositoryAuditLog, long是模块零针对AuditLog实体的标准仓储。AuditLog映射到表AbpAbpAuditLogs[Table(AbpAuditLogs)]实现IMayHaveTenant记录了TenantId、UserId、ServiceName、MethodName、Parameters、ExecutionTime、ExecutionDuration、Exception等审计字段AuditLog.cs更多审计机制见 Audit-Logging.md。关闭租户过滤器AuditLog实现IMayHaveTenant默认受MayHaveTenant数据过滤器约束——在多租户环境中未关闭过滤器时只能看到当前租户的数据。这里用CurrentUnitOfWork.DisableFilter(AbpDataFilters.MayHaveTenant)临时关闭该过滤器常量定义见 AbpDataFilters.cs从而在系统级任务中跨租户统一清理日志过滤器机制详见 Multi-Tenancy.md。删除条件示例代码删除ExecutionTime fiveMinutesAgo的记录即最近 5 分钟内的日志。如果你的意图是删除超过 5 分钟前的旧日志请把条件改为log.ExecutionTime fiveMinutesAgo——清理类任务的通常语义是后者请按业务需要选择。工作单元[UnitOfWork]特性让DoWork在独立工作单元中执行配合CurrentUnitOfWork.SaveChanges()显式提交删除CurrentUnitOfWork由 BackgroundWorkerBase.cs 提供。完成后解决方案结构如下插件类库 应用项目并存构建插件用Release 配置构建插件项目。构建成功后DatabaseMaintainer.dll会生成在DatabaseMaintainer\DatabaseMaintainer\bin\Release\net5.0目录下。说明输出目录中的目标框架名如net5.0取决于插件项目的TargetFramework。插件程序集的目标框架应与宿主应用兼容——例如仓库自带的插件 Demo 项目AbpAspNetCoreDemo.PlugIn目标框架为net9.0其输出路径可从 Startup.cs 中看到请据此调整你项目中实际的框架版本目录。将插件加载进应用在 Startup.cs 中注册插件来源以下示例从wwwroot目录加载插件你也可以把插件目录换成任意路径。需要在目标应用MVC 或 Host 项目的Startup.cs的ConfigureServices中向AddAbp的options追加一行options.PlugInSources.AddFolder(Path.Combine(_hostingEnvironment.WebRootPath, Plugins), SearchOption.AllDirectories);完整的Startup.cs形态如下原文档中的多语句options委托整理为块语法与仓库 Demo 的写法一致见 Startup.cspublic class Startup { private readonly IHostingEnvironment _hostingEnvironment; private readonly IConfigurationRoot _appConfiguration; public Startup(IHostingEnvironment env) { _hostingEnvironment env; _appConfiguration env.GetAppConfiguration(); } public IServiceProvider ConfigureServices(IServiceCollection services) { ... // Configure Abp and Dependency Injection return services.AddAbpAbpProjectNameWebMvcModule(options { // Configure Log4Net logging options.IocManager.IocContainer.AddFacilityLoggingFacility( f f.UseAbpLog4Net().WithConfig(log4net.config) ); // Add plugin source: scan all DLLs under wwwroot/Plugins recursively options.PlugInSources.AddFolder( Path.Combine(_hostingEnvironment.WebRootPath, Plugins), SearchOption.AllDirectories ); }); } ... }关键 API 说明PlugInSources.AddFolder(folder, searchOption)是PlugInSourceList的扩展方法内部创建FolderPlugInSourcePlugInSourceListExtensions.cs。SearchOption.AllDirectories表示递归扫描子目录FolderPlugInSource默认只扫描顶层SearchOption.TopDirectoryOnly构造参数可覆盖FolderPlugInSource.cs。底层扫描逻辑AssemblyHelper.GetAllAssembliesInFolder只收集*.dll与*.exe并逐个Assembly.LoadFile加载AssemblyHelper.cs。除文件夹外还有PlugInSourceList.AddTypeList(params Type[])扩展方法PlugInSourceListExtensions.cs以及直接按 DLL 路径加载的AssemblyFileListPlugInSource——仓库 Demo 应用正是用它在Startup.cs中加载AbpAspNetCoreDemo.PlugIn.dllStartup.cs可作为不依赖wwwroot布局的替代方案。部署插件 DLL把构建出的DatabaseMaintainer.dll复制到应用的.Mvc/wwwroot/Plugins目录由于使用了SearchOption.AllDirectories插件 DLL 放在Plugins下的任意子目录也能被扫描到。运行应用并验证直接运行应用打开应用的日志文件如Logs.txt查看输出。若一切正常你应当能看到工作器周期性打印的日志日志中反复出现DeleteOldAuditLogsWorker is working即代表插件已被成功加载、DatabaseMaintainerModule已完成PostInitialize、后台工作器已按 5 秒周期开始执行。此时配合数据库查询AbpAuditLogs表即可确认删除逻辑是否符合预期。进阶插件内提供控制器与嵌入视图仓库自带 Demotest/aspnet-core-demo/AbpAspNetCoreDemo.PlugIn展示了更完整的插件形态——插件不仅能挂后台任务还能携带 MVC 控制器与嵌入视图插件模块AbpAspNetCoreDemoPlugInModule依赖AbpAspNetCoreModule在PreInitialize中通过Configuration.EmbeddedResources.Sources.Add(new EmbeddedResourceSet(...))把插件程序集内的Views注册为嵌入资源并在Initialize中RegisterAssemblyByConventionAbpAspNetCoreDemoPlugInModule.cs。插件程序集内含Controllers/BlogController.cs与Views/Blog/下的Index.cshtml、Index.css、Index.js随插件 DLL 一起被宿主应用发现并渲染。这印证了插件机制的应用范围远超定时任务在模块零与 ASP.NET Core 集成的基础上插件可以承载完整的功能页签控制器 视图 静态资源。嵌入资源的完整配置方式见 Embedded-Resource-Files.md控制器集成见 MVC-Controllers.md。小结与关键源码索引围绕本文内容可继续深入阅读的仓库源码与文档关注点位置插件来源抽象与三种实现src/Abp/PlugIns/插件装配进启动流程AbpBootstrapper.cs、AbpModuleManager.cs模块判定规则AbpModule.cs周期后台工作器与计时器PeriodicBackgroundWorkerBase.cs、AbpTimer.cs审计日志实体AuditLog.cs多租户数据过滤器AbpDataFilters.cs插件 Demo控制器 嵌入视图AbpAspNetCoreDemo.PlugIn 与 宿主 Startup.cs关联概念文档Module-System.md、Background-Jobs-And-Workers.md、Audit-Logging.md、Multi-Tenancy.md整体来看ABP 插件机制的价值在于按程序集边界拆分功能模块并在不修改宿主代码的前提下完成模块注册、依赖注入与后台任务挂载。把DatabaseMaintainerModule替换成你自己的业务模块重复模块类 RegisterAssemblyByConventionPlugInSources.AddFolder三步即可把任何独立功能以插件形式交付到 ABP 应用中。赞分享后端Web框架依赖注入认证鉴权【免费下载链接】aspnetboilerplateASP.NET Boilerplate - Web Application Framework项目地址https://gitcode.com/gh_mirrors/as/aspnetboilerplate点击查看免费下载相关推荐baoyu-skills 幻灯片技能中的 Vintage 复古纸张样式设计规范、色板体系与提示词工程实战baoyu skills 幻灯片技能中的 Vintage 复古纸张样式设计规范、色板体系与提示词工程实战 baoyu slide deck 是 baoyu sAI 技能AI 插件Eclipse Theia 无头插件Headless Plugin与自定义插件 API 实战以 plugin-gotd 示例插件为例Eclipse Theia 无头插件Headless Plugin与自定义插件 API 实战以 plugin gotd 示例插件为例 本篇技术指南围绕 EIDE代码编辑器开发工具前端桌面应用插件系统后端AI 应用emdash-cms/plugin-audit-logEmDash CMS 内容审计日志插件完整指南emdash cms/plugin audit logEmDash CMS 内容审计日志插件完整指南 本指南以 emdash cms/plugin audCMS后端前端插件系统上一篇Reticulum MeshChat 开发指南从源码构建到自定义功能扩展下一篇堆利用入门从 Exploitarium libssh2 publickey PoC 学任意 free 到 calc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/23 22:50:15

奇诺多面体+CVXPY实现虚拟电厂广域协同调控

简介:本资源聚焦虚拟电厂中空调负荷、储能设备与柴油发电机三类分布式资源的广域聚合调控问题,面向具备优化理论基础与Python编程能力的电力系统研究人员、分布式能源开发工程师及高年级研究生,提供从可行域建模到集群协同优化的完整技术路径…

2026/9/23 22:45:14

医学影像超分辨率重建:EDSR在CT/MRI病灶识别中的临床落地实践

简介:本资源是一份高质量的人工智能毕业设计项目,聚焦深度学习驱动的图像超分辨率重建技术,并拓展至医学影像增强这一典型应用场景,面向计算机、人工智能、自动化及医学信息工程等专业的本科生与初阶研究者,助力课程设…

2026/9/23 23:45:20

嵌入式五大通信接口时序全解析:UART/SPI/I2C/CAN/USB

做嵌入式这些年,无论是带新人、做评审,还是自己调板子,来来回回绕不开的问题就那几个:模块之间用什么通信?信号线怎么接?波形为什么不对?我发现自己面试候选人也特别爱问通信接口,因…

2026/9/23 23:45:20

无源定位椭圆法:被动雷达多站融合定位算法解析

简介:面向无源雷达与被动定位研究场景,这份MATLAB源码实现椭圆法目标定位中的关键步骤——多站观测椭圆交点求解。它根据信号到达时间差/频率差信息构建椭圆模型,通过数值迭代计算目标平面位置,可避免手工解算非线性方程的繁琐并降…

2026/9/23 23:45:20

微信表情包怎么导出成图片素材?做图的人看这里

如果你做图、做贴纸、剪视频,大概遇到过这种卡壳——挑了半天,觉得某个微信表情正好贴合主题,想放进画面里。可你翻遍整个微信,就是拿不出那个「文件」。微信表情导出成图片素材,办法是把它发给「表情保存助手」这个公…

2026/9/23 23:45:20

湘楚有才单招:单招路上,信息差才是最大的不公平

同一个班的学生,成绩差不多,备考时间差不多,最后录取结果却可能差很多。问题出在哪里?很多时候,出在信息差上。有的学生知道目标院校今年扩招了,果断报考,顺利上岸;有的学生不知道,保守填报,浪费了分数。有的学生了解某所学校的职测侧重什么方向,提前针对性准备;有的学生一无所…

2026/9/23 23:40:20

全局规划与局部避障:Astar与DWA算法原理及源码实战

简介:基于Python实现的轮式机器人路径规划工程,融合A星全局路径规划与DWA动态窗口法,适用于机器人导航、自动驾驶等教学科研与个人学习场景。压缩包共50个文件,以13个Python脚本为核心,分别实现A星、DWA与主程序流程&a…

2026/9/23 12:07:00

GAMP 5 基于风险的计算机化系统验证:软件分类与审计追踪实践

简介:《A Risk-Based Approach to Compliant GxP Computerized Systems》即业内熟知的GAMP 5指南,面向制药企业质量与IT合规人员、验证工程师及计算机化系统管理者,用于解决GxP法规环境下系统合规性难以科学落地的问题。文档以风险管理为主线…

2026/9/23 12:06:55

安全托管MSSP实战:从静态防御到人机协同的攻防运营与应急响应

简介:这份PPT围绕互联网业务安全托管服务展开,面向企业安全负责人、IT运维人员及关注MSSP/MSS选型的读者,重点回应传统安全过度依赖人工、碎片化静态防御难以对抗产业化攻击等痛点。资源共1个pptx文件,包体约30.63MB,以…

2026/9/23 0:01:54

3个实战技巧搞定形式英语:从看教程到跑通性能优化

3个实战技巧搞定形式英语:从看教程到跑通性能优化 看了一堆教程还是不会写项目?别慌,这种“眼高手低”的困境在开发者圈子里太常见了。很多人以为卡点在语法,其实真正拦路虎是缺乏将知识点串联成完整链路的能力。今天咱们不聊虚的,直接拿【形式英语】这…

2026/9/22 16:34:32

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/22 20:01:30

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/22 13:25:41

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码