一、前言

最近公司新项目,需要搭架构进行开发,其中需要保证事务的一致性,经过一番查找,发现很多博文都是通过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 定义属性

定义属性,通过当前方法是否包含该属性进行判断开启事务,如果存在该属性则开启事务,否则忽略事务。

事务属性可以设置超时时间、事务范围以及事务隔离级别。

代码如下:

/// <summary>
/// 开启事务属性
/// </summary>
[AttributeUsage(AttributeTargets.Method,Inherited = true)]
public class TransactionCallHandlerAttribute:Attribute
{
/// <summary>
/// 超时时间
/// </summary>
public int Timeout { get; set; } /// <summary>
/// 事务范围
/// </summary>
public TransactionScopeOption ScopeOption { get; set; } /// <summary>
/// 事务隔离级别
/// </summary>
public IsolationLevel IsolationLevel { get; set; } public TransactionCallHandlerAttribute()
{
Timeout = 60;
ScopeOption=TransactionScopeOption.Required;
IsolationLevel=IsolationLevel.ReadCommitted;
}
}

4.2 切面实现

获取当前方法是否包含TransactionCallHandlerAttribute该属性,如果有该属性则开启事务。

本人在此处加入开发模式判断,用于没设置MSDTC产生异常的问题,如果不需要可忽略。

另外日志功能自行实现即可。

代码如下:

/// <summary>
/// 事务 拦截器
/// </summary>
public class TransactionInterceptor:IInterceptor
{
//可自行实现日志器,此处可忽略
/// <summary>
/// 日志记录器
/// </summary>
private static readonly ILog Logger = Log.GetLog(typeof(TransactionInterceptor)); // 是否开发模式
private bool isDev = false;
public void Intercept(IInvocation invocation)
{
if (!isDev)
{
MethodInfo methodInfo = invocation.MethodInvocationTarget;
if (methodInfo == null)
{
methodInfo = invocation.Method;
} TransactionCallHandlerAttribute transaction =
methodInfo.GetCustomAttributes<TransactionCallHandlerAttribute>(true).FirstOrDefault();
if (transaction != null)
{
TransactionOptions transactionOptions = new TransactionOptions();
//设置事务隔离级别
transactionOptions.IsolationLevel = transaction.IsolationLevel;
//设置事务超时时间为60秒
transactionOptions.Timeout = new TimeSpan(0, 0, transaction.Timeout);
using (TransactionScope scope = new TransactionScope(transaction.ScopeOption, transactionOptions))
{
try
{
//实现事务性工作
invocation.Proceed();
scope.Complete();
}
catch (Exception ex)
{
// 记录异常
throw ex;
}
}
}
else
{
// 没有事务时直接执行方法
invocation.Proceed();
}
}
else
{
// 开发模式直接跳过拦截
invocation.Proceed();
}
}
}

4.3 切面注入

博主对Autofac进行了封装,可能与你们的配置不一样,但是,Load(ContainerBuilder builder)该方法内容是一致的,因此注入方式一致的。

通过定义IDependency空接口方式,需要注入的类则继承该接口即可。

代码如下:

/// <summary>
/// 应用程序IOC配置
/// </summary>
public class IocConfig : ConfigBase
{
// 重写加载配置
protected override void Load(ContainerBuilder builder)
{
var assembly = this.GetType().GetTypeInfo().Assembly;
builder.RegisterType<TransactionInterceptor>();
builder.RegisterAssemblyTypes(assembly)
.Where(type => typeof(IDependency).IsAssignableFrom(type) && !type.GetTypeInfo().IsAbstract)
.AsImplementedInterfaces()
.InstancePerLifetimeScope()
.EnableInterfaceInterceptors()
.InterceptedBy(typeof(TransactionInterceptor));
}
}

五、例子

/// <summary>
/// 添加文章
/// </summary>
/// <param name="name"></param>
[TransactionCallHandler]
public void AddArticle(string name)
{
BasArticle model=new BasArticle();
model.ArticleID = Guid.Empty;//故意重复,判断是否会回滚。
model.Code = TimestampId.GetInstance().GetId();
model.Name = name;
model.Status = 1;
model.Creater = "测试";
model.Editor = "测试";
this._basArticleRepository.Insert(model);
}

[AOP系列]Autofac+Castle实现AOP事务的更多相关文章

  1. [AOP系列]Autofac+Castle实现AOP日志

    一.前言 最近公司新项目,需要搭架构进行开发,其中需要对一些日志进行输出,经过一番查找,发现很多博文都是通过Spring.Net.Unity.PostSharp.Castle Windsor这些方式实 ...

  2. .Net中的AOP系列之《将AOP作为架构工具》

    返回<.Net中的AOP>系列学习总目录 本篇目录 编译时初始化和验证 编译时初始化 切面验证的正确用法 真实案例:复习线程 架构约束 强制架构 真实案例:NHibernate 多播 类级 ...

  3. Spring AOP 系列总括

    Spring有两大核心,IOC和AOP.IOC在Java Web项目中无时无刻不在使用,然而AOP用的比较少,尤其是对一些初级程序员,在架构师搭好的框架上开发应用代码,AOP几乎是透明的.然而,项目中 ...

  4. ASP.NET Core中使用IOC三部曲(三.采用替换后的Autofac来实现AOP拦截)

    前言 本文主要是详解一下在ASP.NET Core中,采用替换后的Autofac来实现AOP拦截 觉得有帮助的朋友~可以左上角点个关注,右下角点个推荐 这里就不详细的赘述IOC是什么 以及DI是什么了 ...

  5. Spring系列22:Spring AOP 概念与快速入门篇

    本文内容 Spring AOP含义和目标 AOP相关概念 声明式AOP快速入门 编程式创建代理对象 Spring AOP含义和目标 OOP: Object-oriented Programming 面 ...

  6. Spring框架系列(五)--面向切面AOP

    背景: 当需要为多个不具有继承关系的对象引入一个公共行为,例如日志.权限验证.事务等功能时,如果使用OOP,需要为每个对象引入这些公共 行为.会产生大量重复代码,并且不利用维护.AOP就是为了解决这个 ...

  7. Spring AOP系列(二) — 动态代理引言

    接上一篇Spring AOP系列(一)- 代理模式,本篇来聊聊动态代理. 动态代理与静态代理的区别 要想了解动态代理与静态代理的区别,需要有两个前置知识点:java程序是如何执行的以及类加载机制. j ...

  8. Spring AOP系列(一)— 代理模式

    Spring AOP系列(一)- 代理模式 AOP(Aspect Oriented Programming)并没有创造或使用新的技术,其底层就是基于代理模式实现.因此我们先来学习一下代理模式. 基本概 ...

  9. 框架源码系列十:Spring AOP(AOP的核心概念回顾、Spring中AOP的用法、Spring AOP 源码学习)

    一.AOP的核心概念回顾 https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/core.html#a ...

随机推荐

  1. Spring Boot的properties配置文件读取

    我在自己写点东西玩的时候需要读配置文件,又不想引包,于是打算扣点Spring Boot读取配置文件的代码出来,当然只是读配置文件没必要这么麻烦,不过反正闲着也是闲着,扣着玩了.具体启动过程以前的博客写 ...

  2. Android WebView 不支持 H5 input type="file" 解决方法

    最近因为赶项目进度,因此将本来要用原生控件实现的界面,自己做了H5并嵌入webview中.发现点击H5中 标签 不能打开android资源管理器. 通过网络搜索发现是因为 android webvie ...

  3. Python成长之路 — 字典

    一.字典的定义与创建 字典是Python中唯一内建的映射类型.你可以将其想象成书本的目录,章节名称代表"key",页码则代表"value".书本的目录本质上是也 ...

  4. JavaScript实现图片拖拽、粘贴上传

    前些日子为老婆做了一个web管理商品的工具,因为商品的图片比较多并且还需要剪裁图,为了上传图片方便加了一个拖拽.粘贴上传的功能. 我已经把代码整理出来放到GitHub上了,有兴趣的朋友可以下来玩玩. ...

  5. Windows 7安装Oracle 10g的方法

    Windows7下安装Oracle 10g提示"程序异常终止,发生未知错误"的解决方法 1.修改Oracle 10G\database\stage\prereq\db\refhos ...

  6. Vue2 全家桶仿 微信App 项目,支持多人在线聊天和机器人聊天

    前言 这个项目是利用工作之余写的一个模仿微信app的单页面应用,整个项目包含27个页面,涉及实时群聊,机器人聊天,同学录,朋友圈等等,后续页面还是开发中.写这个项目主要目的是练习和熟悉vue和vuex ...

  7. OFFICE 文档转换为html在线预览

    OFFICE 文档在线预览方案很多: 服务器先转换为PDF,再转换为SWF,最后通过网页加载Flash预览,比如flexpaper Office文档直接转换为SWF,通过网页加载Flash预览 微软的 ...

  8. thinkphp5.0学习笔记(四)数据库的操作

    ThinkPHP内置了抽象数据库访问层,把不同的数据库操作封装起来,我们只需要使用公共的Db类进行操作,而无需针对不同的数据库写不同的代码和底层实现,Db类会自动调用相应的数据库驱动来处理.采用PDO ...

  9. openfire极限优化

    日志优化   默认是 用info 级别,最好不用openfire原生的打日志方式.   离线消息用存储不打回方式,不要用打回方式   xmpp.offline.type=store_and_drop ...

  10. 如何在前端模版引擎开发中避免使用eval函数

    前段时间,想着自己写一个简单的模版引擎,便于自己平时开发demo时使用.于是根据自己对模版引擎的理解,定义自己的模版格式,然后,根据自己定义的格式,编写处理函数,将模版标签中的字符串,解析成可执行的字 ...