Abp Uow 设计
初始化入口
在AbpKernelModule類中,通過(guò)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動(dòng)態(tài)攔截
?
區(qū)分同步異步,通過(guò)UowManager開(kāi)啟事務(wù)
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 } PerformUowinvocation.Proceed();會(huì)嵌套執(zhí)行,將Uow嵌套包含,嵌套的Uow不會(huì)單獨(dú)再開(kāi)啟事務(wù),通過(guò)InnerUnitOfWorkCompleteHandle標(biāo)識(shí),全部完成后complete,提交事務(wù)(UnitOfWorkDefaultOptions默認(rèn)開(kāi)啟事務(wù))
?
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方法中根據(jù)option的設(shè)置,創(chuàng)建了一個(gè)新的Uow,并設(shè)置了Uow相應(yīng)的Completed,Failed,Disposed的方法。
?
?CallContextCurrentUnitOfWorkProvider?
這里有必要提一下CallContextCurrentUnitOfWorkProvider 的對(duì)象,他繼承ICurrentUnitOfWorkProvider
CallContextCurrentUnitOfWorkProvider的主要功能其實(shí)只有一個(gè):通過(guò)current返回當(dāng)前UOW環(huán)境下的UOW實(shí)例。
一般思路是:將IUnitOfWork對(duì)象定義為實(shí)例變量或者是類變量。?但是兩者事實(shí)上都不可行。
如果定義為類變量,那就會(huì)面臨線程安全的問(wèn)題,解決方式無(wú)非加鎖,但會(huì)導(dǎo)致并發(fā)能力下降,ABP是web框架,因?yàn)殒i導(dǎo)致并發(fā)能力下降是不能接受的。
如果定義為實(shí)例變量,在同一線程其他地方resolve?CallContextCurrentUnitOfWorkProvider這個(gè)實(shí)例的時(shí)候都會(huì)得到一個(gè)新的實(shí)例,新的實(shí)例下current自然是NULL.
ABP的做法是:線程邏輯上下文+線程安全的Dictinoray容器。
線程邏輯上下文用于存儲(chǔ)UOW實(shí)例的key,?而線程邏輯上下文對(duì)于本線程是全局可訪問(wèn)的,而同時(shí)具有天然的隔離性。這就確保了當(dāng)前線程的各個(gè)地方都可以得到current的UOW的key
線程安全的Dictinoray容器是一個(gè)類實(shí)例,用于存放UOW的實(shí)例,通過(guò)UOW的key就可以取到UOW的實(shí)例。(引用:?http://www.cnblogs.com/1zhk/p/5309043.html)
這里有兩篇CallContext的博文,推薦看一下
如何實(shí)現(xiàn)對(duì)上下文(Context)數(shù)據(jù)的統(tǒng)一管理 [提供源代碼下載]
CallContext和多線程
?
UnitOfWork
1.UnitOfWorkBase
接下來(lái),分析下UnitOfWork是如何封裝事務(wù)的。
基于接口隔離原則的考量,ABP作者將UnitOfWork的方法分到了三個(gè)不同的接口中,如下圖。
IUnitOfWorkCompleteHandle:定義了UOW同步和異步的complete方法。實(shí)現(xiàn)UOW完成時(shí)候的邏輯。?
IActiveUnitOfWork:一個(gè)UOW除了以上兩個(gè)接口中定義的方法和屬性外,其他的屬性和方法都在這個(gè)接口定義的。比如Completed,Disposed,Failed事件代理,Filter的enable和disable,以及同步、異步的SaveChanges方法。?
IUnitOfWork:繼承了上面兩個(gè)接口。定義了外層的IUnitOfWork的引用和UOW的begin方法。 ABP是通過(guò)構(gòu)建一個(gè)UnitOfWork的鏈,將不同的方法納入到一個(gè)事務(wù)中。
UnitOfWorkBase:這個(gè)抽象類實(shí)現(xiàn)了上面三個(gè)接口中定義的方法,而真正實(shí)現(xiàn)事務(wù)控制的方法是由這個(gè)抽象類的子類實(shí)現(xiàn)的(比如,真正創(chuàng)建TransactionScope的操作是在EfUnitOfWork,NhUnitOfWork這樣的之類中實(shí)現(xiàn)的)。UOW中除了事務(wù)控制邏輯以外的邏輯都是由UnitOfWorkBase抽象類實(shí)現(xiàn)的。?
UnitOfWorkBase中的Begin實(shí)現(xiàn)如下:
1 public void Begin(UnitOfWorkOptions options) 2 { 3 if (options == null) 4 { 5 throw new ArgumentNullException("options"); 6 } 7 8 PreventMultipleBegin(); //通過(guò)_isBeginCalledBefore 字段bool判斷是否已經(jīng)begin 9 Options = options; //TODO: Do not set options like that, instead make a copy? 10 11 SetFilters(options.FilterOverrides); //通過(guò)設(shè)置過(guò)濾器達(dá)到全局?jǐn)?shù)據(jù)過(guò)濾的效果,在ef的實(shí)現(xiàn)中,通過(guò)引用EntityFramework.DynamicFilter實(shí)現(xiàn) 12 13 BeginUow(); 14 }?
2.開(kāi)始UnitOfWork
CompleteUow和BeginUow 在UowBase中為抽象方法,具體實(shí)現(xiàn)在efUow中,稍后分析
/// <summary>/// Should be implemented by derived classes to complete UOW./// </summary>protected abstract void CompleteUow();?
3.Complete
Complete方法在UnitOfWorkInterceptor攔截中,PerformSyncUow方法內(nèi),執(zhí)行完invocation.Proceed();會(huì)調(diào)用Complete方法。
1 /// <inheritdoc/> 2 public void Complete() 3 { 4 PreventMultipleComplete(); //通過(guò)_isCompleteCalledBefore字段Bool判斷是否已經(jīng)Complete,保證只執(zhí)行一次 5 try 6 { 7 CompleteUow(); 8 _succeed = true; 9 OnCompleted(); //調(diào)用完成的事件,在UnitOfWorkManager中設(shè)置,當(dāng)前的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是會(huì)設(shè)置_succeed,沒(méi)有成功則執(zhí)行Faild事件,會(huì)將當(dāng)前的UnitOfWord設(shè)為null 12 { 13 OnFailed(_exception); 14 } 15 16 DisposeUow(); //為抽象方法,在子類中實(shí)現(xiàn) 17 OnDisposed(); //OnFailed和OnDisposed均在UnitOfWordManage中設(shè)置 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( //開(kāi)啟事務(wù),并給定默認(rèn)為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,調(diào)用SaveChange方法 4 if (CurrentTransaction != null) //如果存在事務(wù)則執(zhí)行 5 { 6 CurrentTransaction.Complete(); 7 } 8 }?
轉(zhuǎn)載于:https://www.cnblogs.com/Hai--D/p/5482009.html
總結(jié)
以上是生活随笔為你收集整理的Abp Uow 设计的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: cocos cteator中tiled模
- 下一篇: servlet获取相对路径 绝对路径