Autofac+Castle实现AOP事务

一、前言

最近公司新项目,需要搭架构进行开发,其中需要保证事务的一致性,经过一番查找,发现很多博文都是通过Spring.Net、Unity、PostSharp、Castle Windsor这些方式实现AOP的。但是这不是我想要的,因此一番查找后,使用Autofac、DynamicProxy该方式实现AOP。

二、使用AOP的优势

博主觉得它的优势主要表现在:

  • 将通用功能从业务逻辑中抽离出来,就可以省略大量重复代码,有利于代码的操作和维护。
  • 在软件设计时,抽出通用功能(切面),有利于软件设计的模块化,降低软件架构的复杂程度。也就是说通用的功能就是一个单独的模块,在项目的主业务里面是看不到这些通用功能的设计代码的。

三、引用库

  • Autofac:4.6
  • Autofac.Extras.DynamicProxy:4.1.0
  • Castle.Core:3.2.2

四、实现思路

4.1 定义属性

定义属性,通过当前方法是否包含该属性进行判断开启事务,如果存在该属性则开启事务,否则忽略事务。
事务属性可以设置超时时间、事务范围以及事务隔离级别。
代码如下:

 
  1. /// <summary>

  2. /// 开启事务属性

  3. /// </summary>

  4. [AttributeUsage(AttributeTargets.Method,Inherited = true)]

  5. public class TransactionCallHandlerAttribute:Attribute

  6. {

  7. /// <summary>

  8. /// 超时时间

  9. /// </summary>

  10. public int Timeout { get; set; }

  11. /// <summary>

  12. /// 事务范围

  13. /// </summary>

  14. public TransactionScopeOption ScopeOption { get; set; }

  15. /// <summary>

  16. /// 事务隔离级别

  17. /// </summary>

  18. public IsolationLevel IsolationLevel { get; set; }

  19. public TransactionCallHandlerAttribute()

  20. {

  21. Timeout = 60;

  22. ScopeOption=TransactionScopeOption.Required;

  23. IsolationLevel=IsolationLevel.ReadCommitted;

  24. }

  25. }

4.2 切面实现

获取当前方法是否包含TransactionCallHandlerAttribute该属性,如果有该属性则开启事务。
本人在此处加入开发模式判断,用于没设置MSDTC产生异常的问题,如果不需要可忽略。
另外日志功能自行实现即可。
代码如下:

 
  1. /// <summary>

  2. /// 事务 拦截器

  3. /// </summary>

  4. public class TransactionInterceptor:IInterceptor

  5. {

  6. //可自行实现日志器,此处可忽略

  7. /// <summary>

  8. /// 日志记录器

  9. /// </summary>

  10. private static readonly ILog Logger = Log.GetLog(typeof(TransactionInterceptor));

  11. // 是否开发模式

  12. private bool isDev = false;

  13. public void Intercept(IInvocation invocation)

  14. {

  15. if (!isDev)

  16. {

  17. MethodInfo methodInfo = invocation.MethodInvocationTarget;

  18. if (methodInfo == null)

  19. {

  20. methodInfo = invocation.Method;

  21. }

  22. TransactionCallHandlerAttribute transaction =

  23. methodInfo.GetCustomAttributes<TransactionCallHandlerAttribute>(true).FirstOrDefault();

  24. if (transaction != null)

  25. {

  26. TransactionOptions transactionOptions = new TransactionOptions();

  27. //设置事务隔离级别

  28. transactionOptions.IsolationLevel = transaction.IsolationLevel;

  29. //设置事务超时时间为60秒

  30. transactionOptions.Timeout = new TimeSpan(0, 0, transaction.Timeout);

  31. using (TransactionScope scope = new TransactionScope(transaction.ScopeOption, transactionOptions))

  32. {

  33. try

  34. {

  35. //实现事务性工作

  36. invocation.Proceed();

  37. scope.Complete();

  38. }

  39. catch (Exception ex)

  40. {

  41. // 记录异常

  42. throw ex;

  43. }

  44. }

  45. }

  46. else

  47. {

  48. // 没有事务时直接执行方法

  49. invocation.Proceed();

  50. }

  51. }

  52. else

  53. {

  54. // 开发模式直接跳过拦截

  55. invocation.Proceed();

  56. }

  57. }

  58. }

4.3 切面注入

博主对Autofac进行了封装,可能与你们的配置不一样,但是,Load(ContainerBuilder builder)该方法内容是一致的,因此注入方式一致的。
通过定义IDependency空接口方式,需要注入的类则继承该接口即可。
代码如下:

 
  1. /// <summary>

  2. /// 应用程序IOC配置

  3. /// </summary>

  4. public class IocConfig : ConfigBase

  5. {

  6. // 重写加载配置

  7. protected override void Load(ContainerBuilder builder)

  8. {

  9. var assembly = this.GetType().GetTypeInfo().Assembly;

  10. builder.RegisterType<TransactionInterceptor>();

  11. builder.RegisterAssemblyTypes(assembly)

  12. .Where(type => typeof(IDependency).IsAssignableFrom(type) && !type.GetTypeInfo().IsAbstract)

  13. .AsImplementedInterfaces()

  14. .InstancePerLifetimeScope()

  15. .EnableInterfaceInterceptors()

  16. .InterceptedBy(typeof(TransactionInterceptor));

  17. }

  18. }

五、例子

 
  1. /// <summary>

  2. /// 添加文章

  3. /// </summary>

  4. /// <param name="name"></param>

  5. [TransactionCallHandler]

  6. public void AddArticle(string name)

  7. {

  8. BasArticle model=new BasArticle();

  9. model.ArticleID = Guid.Empty;//故意重复,判断是否会回滚。

  10. model.Code = TimestampId.GetInstance().GetId();

  11. model.Name = name;

  12. model.Status = 1;

  13. model.Creater = "测试";

  14. model.Editor = "测试";

  15. this._basArticleRepository.Insert(model);

  16. }

Castle AOP 系列(二):对接口方法调用的拦截(有源码)_天涯人-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值