[AOP系列]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 定义属性
定义属性,通过当前方法是否包含该属性进行判断开启事务,如果存在该属性则开启事务,否则忽略事务。
事务属性可以设置超时时间、事务范围以及事务隔离级别。
代码如下:
/// <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事务的更多相关文章
- [AOP系列]Autofac+Castle实现AOP日志
一.前言 最近公司新项目,需要搭架构进行开发,其中需要对一些日志进行输出,经过一番查找,发现很多博文都是通过Spring.Net.Unity.PostSharp.Castle Windsor这些方式实 ...
- .Net中的AOP系列之《将AOP作为架构工具》
返回<.Net中的AOP>系列学习总目录 本篇目录 编译时初始化和验证 编译时初始化 切面验证的正确用法 真实案例:复习线程 架构约束 强制架构 真实案例:NHibernate 多播 类级 ...
- Spring AOP 系列总括
Spring有两大核心,IOC和AOP.IOC在Java Web项目中无时无刻不在使用,然而AOP用的比较少,尤其是对一些初级程序员,在架构师搭好的框架上开发应用代码,AOP几乎是透明的.然而,项目中 ...
- ASP.NET Core中使用IOC三部曲(三.采用替换后的Autofac来实现AOP拦截)
前言 本文主要是详解一下在ASP.NET Core中,采用替换后的Autofac来实现AOP拦截 觉得有帮助的朋友~可以左上角点个关注,右下角点个推荐 这里就不详细的赘述IOC是什么 以及DI是什么了 ...
- Spring系列22:Spring AOP 概念与快速入门篇
本文内容 Spring AOP含义和目标 AOP相关概念 声明式AOP快速入门 编程式创建代理对象 Spring AOP含义和目标 OOP: Object-oriented Programming 面 ...
- Spring框架系列(五)--面向切面AOP
背景: 当需要为多个不具有继承关系的对象引入一个公共行为,例如日志.权限验证.事务等功能时,如果使用OOP,需要为每个对象引入这些公共 行为.会产生大量重复代码,并且不利用维护.AOP就是为了解决这个 ...
- Spring AOP系列(二) — 动态代理引言
接上一篇Spring AOP系列(一)- 代理模式,本篇来聊聊动态代理. 动态代理与静态代理的区别 要想了解动态代理与静态代理的区别,需要有两个前置知识点:java程序是如何执行的以及类加载机制. j ...
- Spring AOP系列(一)— 代理模式
Spring AOP系列(一)- 代理模式 AOP(Aspect Oriented Programming)并没有创造或使用新的技术,其底层就是基于代理模式实现.因此我们先来学习一下代理模式. 基本概 ...
- 框架源码系列十:Spring AOP(AOP的核心概念回顾、Spring中AOP的用法、Spring AOP 源码学习)
一.AOP的核心概念回顾 https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/core.html#a ...
随机推荐
- jq、js中判断checkbox是否选中
最近在开发项目时用到checkbox复选框,其中遇到一个问题:在JQ中如何判断checkbox是否被选中呢?之前用JQ获取元素的属性用的都是attr(),但用在checkbox上却没有用,原因何在?? ...
- Web开发安全小贴士
想要开发出一个安全的.健壮的Web应用其实是非常困难的, 如果你想要快速开发出一款集使用价值.用户体验度.以及安全性为一身的产品,以下安全步骤很必要!!! 数据库 1.对类似访问令牌.电子邮箱 ...
- 【JAVAEE学习笔记】hibernate02:实体规则、对象状态、缓存、事务、批量查询和实现客户列表显示
一.hibernate中的实体规则 实体类创建的注意事项 1.持久化类提供无参数构造 2.成员变量私有,提供共有get/set方法访问.需提供属性 3.持久化类中的属性,应尽量使用包装类型 4.持久化 ...
- Html5模拟通讯录人员排序(sen.js)
// JavaScript Document var PY_Json_Str = ""; var PY_Str_1 = ""; var PY_Str_2 = & ...
- Hadoop集群搭建(非HA)
1.准备Linux环境 1.0先将虚拟机的网络模式选为NAT 1.1修改主机名 vi /etc/sysconfig/network NETWORKING=yes HOSTNAME=itcast ### ...
- 你是否也在学习ES6 Promise时遇到过这个问题?
背景 周末闲来无事,随便翻看了一下阮一峰老师的<ES6 标准入门>第2版,ps:之前在阮一峰老师的官网看过电子版,感觉干货满满,所以就买了纸质版:当看到第16章第4节 'Promise.p ...
- 【数据库】Mean web开发 03-MongoDB客户端管理工具NoSQL Manager for MongoDB的使用
简介 Mean是JavaScript的全栈开发框架.更多介绍 用MongoDB实现持久数据的存储是Mean Web全栈开发中的一部分. MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非 ...
- Datatable插件的简单的使用方式 和 学习方式
gridyxz = $("#sjjg_table_yxz").DataTable({ "searching" : false, "info&quo ...
- Webpack 开发工具与模块热替换
Webpack 开发工具与模块热替换 ⚠️ 注意: 永远不要在生产环境中使用这些工具,永远不要. devtool 当 JavaScript 异常抛出时,你常会想知道这个错误发生在哪个文件的哪一行.然 ...
- JavaScript面向对象轻松入门之封装(demo by ES5、ES6、TypeScript)
本章默认大家已经看过作者的前一篇文章 <JavaScript面向对象轻松入门之抽象> 为什么要封装? 封装(Encapsulation)就是把对象的内部属性和方法隐藏起来,外部代码访问该对 ...