• Abp Uow 设计


    初始化入口

    在AbpKernelModule类中,通过UnitOfWorkRegistrar.Initialize(IocManager) 方法去初始化

     1 /// <summary>
     2     /// This class is used to register interceptor for needed classes for Unit Of Work mechanism.
     3     /// </summary>
     4     internal static class UnitOfWorkRegistrar
     5     {
     6         /// <summary>
     7         /// Initializes the registerer.
     8         /// </summary>
     9         /// <param name="iocManager">IOC manager</param>
    10         public static void Initialize(IIocManager iocManager)
    11         {
    12             iocManager.IocContainer.Kernel.ComponentRegistered += ComponentRegistered;
    13         }
    14 
    15         private static void ComponentRegistered(string key, IHandler handler)
    16         {
    17             if (UnitOfWorkHelper.IsConventionalUowClass(handler.ComponentModel.Implementation))
    18             {
    19                 //Intercept all methods of all repositories.
    20                 handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(UnitOfWorkInterceptor)));
    21             }
    22             else if (handler.ComponentModel.Implementation.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Any(UnitOfWorkHelper.HasUnitOfWorkAttribute))
    23             {
    24                 //Intercept all methods of classes those have at least one method that has UnitOfWork attribute.
    25                 //TODO: Intecept only UnitOfWork methods, not other methods!
    26                 handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(UnitOfWorkInterceptor)));
    27             }
    28         }
    29     }
    UnitOfWorkRegistrar

    UnitOfWorkInterceptor 拦截器

    基于Castle.Core的AOP动态拦截

     

    区分同步异步,通过UowManager开启事务

     1 private void PerformUow(IInvocation invocation, UnitOfWorkOptions options)
     2         {
     3             if (AsyncHelper.IsAsyncMethod(invocation.Method))
     4             {
     5                 PerformAsyncUow(invocation, options);
     6             }
     7             else
     8             {
     9                 PerformSyncUow(invocation, options);
    10             }
    11         }
    12 
    13         private void PerformSyncUow(IInvocation invocation, UnitOfWorkOptions options)
    14         {
    15             using (var uow = _unitOfWorkManager.Begin(options))
    16             {
    17                 invocation.Proceed();
    18                 uow.Complete();
    19             }
    20         }
    PerformUow

    invocation.Proceed();会嵌套执行,将Uow嵌套包含,嵌套的Uow不会单独再开启事务,通过InnerUnitOfWorkCompleteHandle标识,全部完成后complete,提交事务(UnitOfWorkDefaultOptions默认开启事务)

    UnitOfWorkManager

    UnitOfWorkManager 继承IUnitOfWorkManager

     1 /// <summary>
     2     /// Unit of work manager.
     3     /// Used to begin and control a unit of work.
     4     /// </summary>
     5     public interface IUnitOfWorkManager
     6     {
     7         /// <summary>
     8         /// Gets currently active unit of work (or null if not exists).
     9         /// </summary>
    10         IActiveUnitOfWork Current { get; }
    11 
    12         /// <summary>
    13         /// Begins a new unit of work.
    14         /// </summary>
    15         /// <returns>A handle to be able to complete the unit of work</returns>
    16         IUnitOfWorkCompleteHandle Begin();
    17 
    18         /// <summary>
    19         /// Begins a new unit of work.
    20         /// </summary>
    21         /// <returns>A handle to be able to complete the unit of work</returns>
    22         IUnitOfWorkCompleteHandle Begin(TransactionScopeOption scope);
    23 
    24         /// <summary>
    25         /// Begins a new unit of work.
    26         /// </summary>
    27         /// <returns>A handle to be able to complete the unit of work</returns>
    28         IUnitOfWorkCompleteHandle Begin(UnitOfWorkOptions options);
    29     }
    IUnitOfWorkManager

     

    在Begin方法中根据option的设置,创建了一个新的Uow,并设置了Uow相应的Completed,Failed,Disposed的方法。

     

     CallContextCurrentUnitOfWorkProvider 

    这里有必要提一下CallContextCurrentUnitOfWorkProvider 的对象,他继承ICurrentUnitOfWorkProvider

    CallContextCurrentUnitOfWorkProvider的主要功能其实只有一个:通过current返回当前UOW环境下的UOW实例。

    一般思路是:将IUnitOfWork对象定义为实例变量或者是类变量。 但是两者事实上都不可行。

    如果定义为类变量,那就会面临线程安全的问题,解决方式无非加锁,但会导致并发能力下降,ABP是web框架,因为锁导致并发能力下降是不能接受的。

    如果定义为实例变量,在同一线程其他地方resolve CallContextCurrentUnitOfWorkProvider这个实例的时候都会得到一个新的实例,新的实例下current自然是NULL.

    ABP的做法是:线程逻辑上下文+线程安全的Dictinoray容器。

    线程逻辑上下文用于存储UOW实例的key, 而线程逻辑上下文对于本线程是全局可访问的,而同时具有天然的隔离性。这就确保了当前线程的各个地方都可以得到current的UOW的key

    线程安全的Dictinoray容器是一个类实例,用于存放UOW的实例,通过UOW的key就可以取到UOW的实例。(引用: http://www.cnblogs.com/1zhk/p/5309043.html)

    这里有两篇CallContext的博文,推荐看一下

    CallContext和多线程

    UnitOfWork

    1.UnitOfWorkBase

    接下来,分析下UnitOfWork是如何封装事务的。

    基于接口隔离原则的考量,ABP作者将UnitOfWork的方法分到了三个不同的接口中,如下图。

    IUnitOfWorkCompleteHandle:定义了UOW同步和异步的complete方法。实现UOW完成时候的逻辑。 

    IActiveUnitOfWork:一个UOW除了以上两个接口中定义的方法和属性外,其他的属性和方法都在这个接口定义的。比如Completed,Disposed,Failed事件代理,Filter的enable和disable,以及同步、异步的SaveChanges方法。 

    IUnitOfWork:继承了上面两个接口。定义了外层的IUnitOfWork的引用和UOW的begin方法。 ABP是通过构建一个UnitOfWork的链,将不同的方法纳入到一个事务中。
    UnitOfWorkBase:这个抽象类实现了上面三个接口中定义的方法,而真正实现事务控制的方法是由这个抽象类的子类实现的(比如,真正创建TransactionScope的操作是在EfUnitOfWorkNhUnitOfWork这样的之类中实现的)。UOW中除了事务控制逻辑以外的逻辑都是由UnitOfWorkBase抽象类实现的。 

     1     /// <summary>
     2     /// Defines a unit of work.
     3     /// This interface is internally used by ABP.
     4     /// Use <see cref="IUnitOfWorkManager.Begin()"/> to start a new unit of work.
     5     /// </summary>
     6     public interface IUnitOfWork : IActiveUnitOfWork, IUnitOfWorkCompleteHandle
     7     {
     8         /// <summary>
     9         /// Unique id of this UOW.
    10         /// </summary>
    11         string Id { get; }
    12 
    13         /// <summary>
    14         /// Reference to the outer UOW if exists.
    15         /// </summary>
    16         IUnitOfWork Outer { get; set; }
    17         
    18         /// <summary>
    19         /// Begins the unit of work with given options.
    20         /// </summary>
    21         /// <param name="options">Unit of work options</param>
    22         void Begin(UnitOfWorkOptions options);
    23     }
    IUnitOfWork

    UnitOfWorkBase中的Begin实现如下:

     1 public void Begin(UnitOfWorkOptions options)
     2         {
     3             if (options == null)
     4             {
     5                 throw new ArgumentNullException("options");
     6             }
     7 
     8             PreventMultipleBegin();      //通过_isBeginCalledBefore 字段bool判断是否已经begin
     9             Options = options; //TODO: Do not set options like that, instead make a copy?
    10 
    11             SetFilters(options.FilterOverrides);    //通过设置过滤器达到全局数据过滤的效果,在ef的实现中,通过引用EntityFramework.DynamicFilter实现
    12 
    13             BeginUow();
    14         }

    2.开始UnitOfWork

    CompleteUow和BeginUow 在UowBase中为抽象方法,具体实现在efUow中,稍后分析

            /// <summary>
            /// Should be implemented by derived classes to complete UOW.
            /// </summary>
            protected abstract void CompleteUow();    

    3.Complete

    Complete方法在UnitOfWorkInterceptor拦截中,PerformSyncUow方法内,执行完invocation.Proceed();会调用Complete方法。

     1         /// <inheritdoc/>
     2         public void Complete()
     3         {
     4             PreventMultipleComplete();    //通过_isCompleteCalledBefore字段Bool判断是否已经Complete,保证只执行一次
     5             try
     6             {
     7                 CompleteUow();
     8                 _succeed = true;
     9                 OnCompleted();        //调用完成的事件,在UnitOfWorkManager中设置,当前的UnitOfWork为null
    10             }
    11             catch (Exception ex)
    12             {
    13                 _exception = ex;
    14                 throw;
    15             }
    16         }    

    4.Dispose

     1         /// <inheritdoc/>
     2         public void Dispose()
     3         {
     4             if (IsDisposed)
     5             {
     6                 return;
     7             }
     8 
     9             IsDisposed = true;
    10 
    11             if (!_succeed)          //在Complete是会设置_succeed,没有成功则执行Faild事件,会将当前的UnitOfWord设为null
    12             {
    13                 OnFailed(_exception);
    14             }
    15 
    16             DisposeUow();          //为抽象方法,在子类中实现
    17             OnDisposed();          //OnFailed和OnDisposed均在UnitOfWordManage中设置
    18         }    

    EfUnitOfWork

    1.BeginUow

     1         protected override void BeginUow()
     2         {
     3             if (Options.IsTransactional == true)
     4             {
     5                 var transactionOptions = new TransactionOptions
     6                 {
     7                     IsolationLevel = Options.IsolationLevel.GetValueOrDefault(IsolationLevel.ReadUncommitted),
     8                 };
     9 
    10                 if (Options.Timeout.HasValue)
    11                 {
    12                     transactionOptions.Timeout = Options.Timeout.Value;
    13                 }
    14 
    15                 CurrentTransaction = new TransactionScope(                      //开启事务,并给定默认为Required
    16                     Options.Scope.GetValueOrDefault(TransactionScopeOption.Required),
    17                     transactionOptions,
    18                     Options.AsyncFlowOption.GetValueOrDefault(TransactionScopeAsyncFlowOption.Enabled)
    19                     );
    20             }
    21         }

     2.CompleteUow

    1         protected override void CompleteUow()
    2         {
    3             SaveChanges();              //遍历EfContent,调用SaveChange方法
    4             if (CurrentTransaction != null)    //如果存在事务则执行
    5             {
    6                 CurrentTransaction.Complete();
    7             }
    8         }
  • 相关阅读:
    使用Logstash把MySQL数据导入到Elasticsearch中
    通过Metricbeat实现外部对Elastic Stack的监控
    使用Elasticsearch的processors来对csv格式数据进行解析
    redis学习网址
    部署文件:filebeat->kafka集群(zk集群)->logstash->es集群->kibana
    ios实例开发精品文章推荐(8.13)
    ios实例开发精品文章推荐(8.12)11个处理触摸事件和多点触摸的JS库
    Android开发环境——模拟器AVD相关内容汇总
    Android开发环境——Eclipse ADT相关内容汇总
    Android开发环境——SDK相关内容汇总
  • 原文地址:https://www.cnblogs.com/Hai--D/p/5482009.html
Copyright © 2020-2023  润新知