运用Unity实现AOP拦截器[结合异常记录实例]
|
本篇文章将通过Unity实现Aop异常记录功能;有关Unity依赖注入可以看前两篇文章: 另早期写过一个利用Spring.net实现相同的功能:spring.net结合普通三层(实现IOC 及AOP中的异常记录功能) |
一:理论知识
AOP(Aspect-Oriented Programming,面向切面的编程),它是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。它是一种新的方法论,它是对传统OOP编程的一种补充。 OOP是关注将需求功能划分为不同的并且相对独立,封装良好的类,并让它们有着属于自己的行为,依靠继承和多态等来定义彼此的关系;AOP是希望能够将通用需求功能从不相关的类当中分离出来,能够使得很多类共享一个行为,一旦发生变化,不必修改很多类,而只需要修改这个行为即可。 AOP是使用切面(aspect)将横切关注点模块化,OOP是使用类将状态和行为模块化。在OOP的世界中,程序都是通过类和接口组织的,使用它们实现程序的核心业务逻辑是十分合适。但是对于实现横切关注点(跨越应用程序多个模块的功能需求)则十分吃力,比如日志记录,验证等
Unity默认提供了三种拦截器:TransparentProxyInterceptor、InterfaceInterceptor、VirtualMethodInterceptor。
TransparentProxyInterceptor:代理实现基于.NET Remoting技术,它可拦截对象的所有函数。缺点是被拦截类型必须派生于MarshalByRefObject。
InterfaceInterceptor:只能对一个接口做拦截,好处时只要目标类型实现了指定接口就可以拦截。
VirtualMethodInterceptor:对virtual函数进行拦截。缺点是如果被拦截类型没有virtual函数则无法拦截,这个时候如果类型实现了某个特定接口可以改用
InterfaceInterceptor。
二:实例介绍
本实例是通过Unity实现异常的统一记录,解决以前在解决方法不同地方出现重复异常记录情况;

图中同样是基于我们前两篇文章讲解依赖注入时的分层结构;增加对log4net.dll引用来记录异常的内容;
若要了解分层情况看前一篇运用Unity实现依赖注入[结合简单三层实例],本文侧重讲解AOP的实现;
三:实例编码
1:首先了解公共助手层Command;其中Log4netFile加载log4net配置信息,特别要注意assembly
using log4net;
using log4net.Core;
using System.Reflection; [assembly: log4net.Config.XmlConfigurator(Watch = true)]
namespace Command
{
public class Log4NetFile
{
private ILog logger;
public Log4NetFile()
{
logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo("Log4Net.config"));
} public void Log(string message)
{
logger.Warn(message);
} public void Log(Exception ex)
{
logger.Warn("异常的内容:", ex);
}
}
}
而ExceptionLogBehavior类是我们异常拦截器,也是本篇的重点,其中我们继承IInterceptionBehavior接口,不仅可以查看传入的参数,还可以对它进行统一的异常处理;getNext()(input, getNext)就是重调运行;
using Microsoft.Practices.Unity.InterceptionExtension;
namespace Command
{
public class ExceptionLogBehavior:IInterceptionBehavior
{
/// <summary>
/// 获取当前行为需要拦截的对象类型接口。
/// </summary>
/// <returns>所有需要拦截的对象类型接口。</returns>
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
/// <summary>
/// 通过实现此方法来拦截调用并执行所需的拦截行为。
/// </summary>
/// <param name="input">调用拦截目标时的输入信息。</param>
/// <param name="getNext">通过行为链来获取下一个拦截行为的委托。</param>
/// <returns>从拦截目标获得的返回信息。</returns>
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Console.WriteLine("执行前");
IMethodReturn retvalue = getNext()(input, getNext); #region 参数部分
Console.WriteLine("-------------参数内容---------------");
for (int i = ; i < input.Arguments.Count; i++)
{
var parameter = input.Arguments[i];
Console.WriteLine(string.Format("第{0}个参数值为:{1}", i+, parameter.ToString()));
}
Console.WriteLine("------------------------------------");
#endregion #region 异常处理部分
if (retvalue.Exception == null)
{
Console.WriteLine("执行成功,无异常");
}
else
{
//记录异常的内容 比如Log4Net等
new Log4NetFile().Log("异常的内容为:" + retvalue.Exception.Message);
//retvalue.Exception设为null表示异常已经被处理过了
retvalue.Exception = null;
}
#endregion
Console.WriteLine("完成");
return retvalue;
} /// <summary>
/// 获取一个<see cref="Boolean"/>值,该值表示当前拦截行为被调用时,是否真的需要执行
/// 某些操作。
/// </summary>
public bool WillExecute
{
get { return true; }
}
}
2:逻辑层我们故意让它抛出异常内容
using IAopDAL;
using IAopBLL;
using Command;
namespace AopBLL
{
public class ReadDataBLL:IReadDataBLL
{
IReadData bllServer = new UnityContainerHelp().GetServer<IReadData>();
public string ReadDataStr(string Name)
{
throw new Exception("BLL出现异常");
}
}
}
3:主程序层(Aopunity)主要关注配置信息
a:首先是Log4Net.config,每天生成一个.txt文件记录异常内容
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="System.Configuration.IgnoreSectionHandler" />
</configSections>
<log4net>
<appender name="RollingLogRootFileAppender" type="log4net.Appender.RollingFileAppender">
<!--日志的路径-->
<file value=".\Log\WanLog" />
<!--是否覆盖,默认是追加true-->
<appendToFile value="true"/>
<!--文件滚动周期(每日创建新日志文件)-->
<datePattern value="yyyyMMdd".txt""/>
<!--设置无限备份=- ,最大备份数为1000-->
<maxSizeRollBackups value=""/>
<!--名称是否可以更改为false为可以更改-->
<staticLogFileName value="false" />
<!--文件滚动选项Composite表示根据日期和大小来滚动-->
<rollingStyle value="Composite" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss}[%t][%-5p][%c]%m%n%exception%n" />
</layout>
</appender>
<root>
<level value="All" />
<appender-ref ref="RollingLogRootFileAppender" />
</root>
</log4net>
</configuration>
b:App.config则是一些依赖注入跟Aop的配置,增加sectionExtension节点引用;interceptor则表示拦截器的类型,interceptionBehavior对应处理程序,lifetime生命周期
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity xmlns="http://schemas.microsoft.com/practces/2010/unity">
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration"/>
<typeAliases>
<typeAlias alias="transient" type="Microsoft.Practices.Unity.TransientLifetimeManager, Microsoft.Practices.Unity"/>
</typeAliases>
<alias alias="ExceptionLogBehaviorName" type="Command.ExceptionLogBehavior,Command"></alias>
<container name="FirstClass">
<extension type="Interception"/>
<register type="IAopBLL.IReadDataBLL,IAopBLL" mapTo="AopBLL.ReadDataBLL,AopBLL">
<interceptor type="InterfaceInterceptor"/>
<interceptionBehavior type="ExceptionLogBehaviorName"/>
<lifetime type="transient"></lifetime>
</register>
<register type="IAopBLL.IPropertyBLL,IAopBLL" mapTo="AopBLL.PropertyBLL,AopBLL"></register>
<register type="IAopDAL.IReadData,IAopDAL" mapTo="AopOracelDAL.ReadDataDAL,AopOracelDAL"/>
</container>
</unity>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
c:主程序运行代码如下:
using IAopBLL;
using Command;
namespace AopUnity
{
class Program
{
static void Main(string[] args)
{
IReadDataBLL bllServer = new UnityContainerHelp().GetServer<IReadDataBLL>();
Console.WriteLine(bllServer.ReadDataStr("踏浪帅"));
}
}
}
四:运行效果


五:注意事项
1:主程序没有对Microsoft.Practices.Unity.Interception.Configuration.dll进行引用报错

创建 unity 的配置节处理程序时出错: 给定程序集名称或基本代码无效。 (异常来自 HRESULT:0x80131047)
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension,
Microsoft.Practices.Unity.Interception.Configuration"/>
解决方法:主要是我们配置文件中有,则要对它进行引用

2:因为我们把log4net配置文件单独出来,所以要设置其为始终复制

如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】按钮,若有不足欢迎指正。 因为,我的写作热情也离不开您的肯定支持。
感谢您的阅读(源代码下载)
运用Unity实现AOP拦截器[结合异常记录实例]的更多相关文章
- 运用Unity实现AOP拦截器
运用Unity实现AOP拦截器[结合异常记录实例] 本篇文章将通过Unity实现Aop异常记录功能:有关Unity依赖注入可以看前两篇文章: 1:运用Unity实现依赖注入[结合简单三层实例] 2:运 ...
- C# unity 的 IInterceptionBehavior实现aop拦截器
以前项目写过使用unity的 IInterceptionBehavior 实现aop拦截器,时间不多就忘了,项目找不到了,然后呢,写个简单的例子,用的收直接用就行了,简单实用,至于什么用,mvc的at ...
- 从零开始学 Java - Spring AOP 拦截器的基本实现
一个程序猿在梦中解决的 Bug 没有人是不做梦的,在所有梦的排行中,白日梦最令人伤感.不知道身为程序猿的大家,有没有睡了一觉,然后在梦中把睡之前代码中怎么也搞不定的 Bug 给解决的经历?反正我是有过 ...
- Java - Spring AOP 拦截器的基本实现
一个程序猿在梦中解决的 Bug 没有人是不做梦的,在所有梦的排行中,白日梦最令人伤感.不知道身为程序猿的大家,有没有睡了一觉,然后在梦中把睡之前代码中怎么也搞不定的 Bug 给解决的经历?反正我是有过 ...
- 运用Unity结合PolicyInjection实现拦截器[结合操作日志实例]
上一篇文章我们通过Unity自身Unity.InterceptionExtension.IInterceptionBehavior实现一个有系统关异常日志记录:解决代码中到处充满的异常记录的代码: 本 ...
- 基于Dynamic Proxy技术的方法AOP拦截器开发
在面向对象编程中,会用到大量的类,并且会多次调用类中的方法.有时可能需要对这些方法的调用进行一些控制.如在权限管理中,一些用户没有执行某些方法的权限.又如在日志系统中,在某个方法执行完后,将其执行的结 ...
- Spring学习总结(15)——Spring AOP 拦截器的基本实现
一个程序猿在梦中解决的 Bug 没有人是不做梦的,在所有梦的排行中,白日梦最令人伤感.不知道身为程序猿的大家,有没有睡了一觉,然后在梦中把睡之前代码中怎么也搞不定的 Bug 给解决的经历?反正我是有过 ...
- 关于SpringMVC拦截器和异常
一.文件上传 1.文件上传 SpringMVC为文件上传提供了直接的支持,这种类型是通过即插即用的MultipartResolver技术的.Spring用Jakarta Commons FileUpl ...
- 【SpringMVC】文件上传与下载、拦截器、异常处理器
文件下载 使用ResponseEntity实现下载文件的功能 index.html <!DOCTYPE html> <html lang="en" xmlns:t ...
随机推荐
- Shiro的认证原理(Subject#login的背后故事)
登录操作一般都是我们触发的: Subject subject = SecurityUtils.getSubject(); AuthenticationToken authenticationToken ...
- HDU 5861 Road(线段树 区间修改 单点查询)
Road Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submi ...
- 安装zabbix监控系统
环境 操作系统 最小化安装CentOS Linux release 7.2.1511 IP 192.168.88.1 zabbix版本 zabbix-3.4.4.tar.gz zabbix依赖于LNM ...
- leetcode136 Single Number
题意:数组中每个数字都出现了两次,只有一个出现一次,找出这个数 思路:很明显不能从头到位遍历来找,首先是超时的原因,再次就是这样很没意思·····但是却没想到什么好办法,因为不了解按位异或(XOR). ...
- ASP.NET总结——更改后
这篇重新整理的总结,我做了很久,也在草稿箱中放了很久,一直感觉没有达到和老师谈话后的水平,感觉还是需要增加一些修改,希望读者能提出宝贵意见.既这篇博客之前,我发表了一篇ASP.net的总结,在结构上, ...
- bzoj 2159: Crash 的文明世界
Time Limit: 10 Sec Memory Limit: 259 MB Submit: 480 Solved: 234[Submit][Status][Discuss] Descripti ...
- 【拓扑排序】【bitset】Gym - 101128A - Promotions
给你一张DAG,若选择u点,则必须先选择所有能到达其的点.问你在选择A个点的情况下,哪些点必选:选择B个点的情况下,哪些点必选:选择B个点的情况下,哪些点一定不选. 选择A个点的情况,必选的点是那些其 ...
- 【Java】【高精度】【递推】UVA - 11375 - Matches
d[i+c[j]]+=d[i](c[j]是拼成j所需的火柴数) d[0]=1: 别忘了不能有前导零,所以当i为零时,不要尝试去拼成零.反而应该在n>=6时,最后给答案加1(单独拼出0). imp ...
- Codeforces Round #114 (Div. 1) C. Wizards and Numbers 博弈论
C. Wizards and Numbers 题目连接: http://codeforces.com/problemset/problem/167/C Description In some coun ...
- CentOS 6.9配置网卡IP/网关/DNS命令详细介绍及一些常用网络配置命令(转)
一.IP 即时生效(重启后失效): ifconfig eth0 192.168.1.102 netmask 255.255.255.0 //添加IP地址 route add default gw 19 ...