[Abp 源码分析]六、工作单元的实现

在 Abp 框架内部实现了工作单元,在这里讲解一下,什么是工作单元?

Unit Of Work(工作单元)模式用来维护一个由已经被业务事物修改(增加、删除或更新)的业务对象组成的列表。Unit  Of Work模式负责协调这些修改的持久化工作以及所有标记的并发问题。在数据访问层中采用Unit Of Work模式带来的好处是能够确保数据完整性。如果在持久化一系列业务对象(他们属于同一个事物)的过程中出现问题,那么应该将所有的修改回滚,以确保数据始终处于有效状态。

而在 Abp 的内部则是结合 Castle 的 Dynamic Proxy 拦截 UnitOfwork Attribute 来进行动态代理注入,实现了当执行标注了 [UnitOfwork] 方法时能够通过 UnitOfworkManager 来进行事务控制。

其大概流程如下:

[Abp 源码分析]六、工作单元的实现

1 启动流程

首先我们来看一下 Abp 内部是什么时候注入 UOW 相关的代码的,翻阅源码,在 AbpBootstrapper 内部我们就可以看到 Abp 作者为 UOW 写了一个拦截器,并且在 Abp 框架初始化的时候就通过 AddInterceptorRegistrars() 方法来监听 IocManager 的组件注册事件,当触发事件的时候就来判断是否满足条件,如果满足则将拦截器与该类型进行一个绑定。

public class AbpBootstrapper : IDisposable { private AbpBootstrapper([NotNull] Type startupModule, [CanBeNull] Action<AbpBootstrapperOptions> optionsAction = null) { // 其他代码 if (!options.DisableAllInterceptors) { // 添加拦截器 AddInterceptorRegistrars(); } } private void AddInterceptorRegistrars() { ValidationInterceptorRegistrar.Initialize(IocManager); AuditingInterceptorRegistrar.Initialize(IocManager); EntityHistoryInterceptorRegistrar.Initialize(IocManager); UnitOfWorkRegistrar.Initialize(IocManager); AuthorizationInterceptorRegistrar.Initialize(IocManager); } } internal static class UnitOfWorkRegistrar { public static void Initialize(IIocManager iocManager) { // 监听组件注册事件 iocManager.IocContainer.Kernel.ComponentRegistered += (key, handler) => { var implementationType = handler.ComponentModel.Implementation.GetTypeInfo(); // 按 UOW 特性注册 HandleTypesWithUnitOfWorkAttribute(implementationType, handler); // 按规约注册 HandleConventionalUnitOfWorkTypes(iocManager, implementationType, handler); }; } private static void HandleTypesWithUnitOfWorkAttribute(TypeInfo implementationType, IHandler handler) { if (IsUnitOfWorkType(implementationType) || AnyMethodHasUnitOfWork(implementationType)) { handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(UnitOfWorkInterceptor))); } } private static void HandleConventionalUnitOfWorkTypes(IIocManager iocManager, TypeInfo implementationType, IHandler handler) { if (!iocManager.IsRegistered<IUnitOfWorkDefaultOptions>()) { return; } var uowOptions = iocManager.Resolve<IUnitOfWorkDefaultOptions>(); if (uowOptions.IsConventionalUowClass(implementationType.AsType())) { handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(UnitOfWorkInterceptor))); } } private static bool IsUnitOfWorkType(TypeInfo implementationType) { return UnitOfWorkHelper.HasUnitOfWorkAttribute(implementationType); } private static bool AnyMethodHasUnitOfWork(TypeInfo implementationType) { return implementationType .GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .Any(UnitOfWorkHelper.HasUnitOfWorkAttribute); } }

可以看到在这个 Registrar 里面他拥有两种注册方式,第一种很简单,就是判断注册的组件类型是否拥有 UOW 标签,第二种则是通过规约来注入拦截器。

Abp 默认针对仓储与应用服务会自动将拦截器挂载到这两个类型以及他的所有子类的。这里的 UnitOfWorkDefaultOptionsExtensions.IsConventionalUowClass() 方法就是用来判断传入的 Type 是否属于规约的 Type。

public static bool IsConventionalUowClass(this IUnitOfWorkDefaultOptions unitOfWorkDefaultOptions, Type type) { return unitOfWorkDefaultOptions.ConventionalUowSelectors.Any(selector => selector(type)); }

又牵扯到了一个 IUnitOfWorkDefaultOptions ,看一下他的默认实现 UnitOfWorkDefaultOptions 就会发现这样的代码:

public UnitOfWorkDefaultOptions() { _filters = new List<DataFilterConfiguration>(); IsTransactional = true; Scope = TransactionScopeOption.Required; IsTransactionScopeAvailable = true; // 默认类型 ConventionalUowSelectors = new List<Func<Type, bool>> { type => typeof(IRepository).IsAssignableFrom(type) || typeof(IApplicationService).IsAssignableFrom(type) }; } 2. 实现原理 2.1 工作单元拦截器

在上一步我们通过两种注入方式将拦截器注入到需要应用工作单元特性的类型里面,那么我们程序在执行的时候就会使用 Dyncmic Proxy 来拦截包裹这些方法。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpyzds.html