不用Unity库,利用.NET动态代理自己实现AOP
AOP意为面向切面的程序设计,主要表现为对不同的代码逻辑进行隔离,从而降低不同业务逻辑之间的耦合性,AOP又理解为“横切”,可以在不改变原有实现的情况下,对代码进行拦截和扩展,如果原有设计像一个瓶子,AOP就相当于一个贴纸,是贴在瓶子外面的,而不是打开瓶盖从瓶口把实现放进瓶子里。
.NET中实现AOP的第三方库有很多,这里不再阐述了,在这里我们主要用到了.NET中的动态代理技术,为了让大家更深入地理解,这里借用一下上一篇文章(不用Unity库,自己实现.NET轻量级依赖注入)中的例子,在上一篇文章中,我们自己实现了一个轻量级的依赖注入,在这里我们准备用.NET动态代理对依赖注入的方法进行拦截和扩展。
在大部分系统中,日志和权限都是很常见的功能,我们给自己实现的依赖注入加上AOP的功能,使得所有方法自动实现日志记录和权限验证的功能,首先我们来实现一个公共的权限代理类:
/// <summary> /// 权限验证代理类 /// </summary> public class AuthorizeProxy : IInterceptor { public void Intercept(IInvocation invocation) { //判断是否授权 if (HttpContext.Current.User.Identity.IsAuthenticated) { invocation.Proceed(); } else { throw new Exception("没有权限!"); } } }
这里要特别说明一下,我们并没有使用原生的Emit来实现动态代理,而是使用了微软的Castle开源库,这个地方需要引用Castle.Core.dll,我们的权限代理类继承自IInterceptor接口,并实现接口中的拦截方法,首先判断是否授权,有授权就利用invocation.Proceed()继续执行,没有授权就抛出异常。接下来看一下怎么在我们的依赖注入中使用该代理类:
public sealed class DependencyInjector { /// <summary> /// 根据名称和构造函数的参数加载相应的类 /// </summary> /// <typeparam name="T">需要加载的类所实现的接口</typeparam> /// <param name="className">类的名称</param> /// <param name="args">构造函数的参数(默认为空)</param> /// <returns>类的接口</returns> public static T GetClass<T>(string className, object[] args = null) where T : class { //获取接口所在的命名空间 string factoryName = typeof(T).Namespace; //通过依赖注入配置文件获取接口实现所在的命名空间 string dllName = ConfigurationManager.AppSettings[factoryName]; //获取类的全名 string fullClassName = dllName + "." + className; //根据dll和类名,利用反射加载类 object classObject = Assembly.Load(dllName).CreateInstance(fullClassName, true, BindingFlags.Default, null, args, null, null); var generator = new ProxyGenerator(); //使用动态代理覆盖原来的类 object classProxy = generator.CreateClassProxy(classObject.GetType(),new IInterceptor[] { new AuthorizeProxy() }); return classProxy as T; } }
这段代码和上一篇文章不同的是:得到依赖注入的实现以后,并没有直接返回给调用,而是利用Castle库和我们定义的权限代理类,生成了一个动态代理返回给了调用,这时候如果调用了类中的方法,AuthorizeProxy中的权限验证就会自动执行。接下来我们再添加一个日志的代理类,用于记录每个方法调用的耗时:
public class LogProxy : IInterceptor { public void Intercept(IInvocation invocation) { StringBuilder log = new StringBuilder(); log.AppendLine(invocation.Method.ReflectedType + "." + invocation.Method.Name + "开始执行..."); DateTime start = DateTime.Now; //这里还可以加上其他的日志... invocation.Proceed(); log.AppendLine(invocation.Method.ReflectedType + "." + invocation.Method.Name + "执行结束,耗时:" + (DateTime.Now - start)); ErrerLogService<NormalLog>.LogWriter(new NormalLog(log.ToString())); } }
这段代码和权限验证的代码很像,都是实现了IInterceptor接口的拦截方法,在代码的执行前后都加上日志,并在方法执行完毕后,记录执行时间,同时添加这两个代理类,可以这样:
generator.CreateClassProxy(classObject.GetType(),new IInterceptor[] { new LogProxy(),new AuthorizeProxy() });
因为CreateClassProxy接收的是一个数组,这里可以把日志和权限的功能同时加进去。通过这种实现方法我们可以看出:
1.在我们没有更改业务代码的情况实现的日志记录和权限验证(解耦)。
2.我们可以方便地对原有功能进行扩展(扩展性)。
3.AOP提高了我们的开发效率(代码复用)。
不用Unity库,利用.NET动态代理自己实现AOP的更多相关文章
- 利用JDK动态代理机制实现简单拦截器
利用JDK动态代理机制实现简单的多层拦截器 首先JDK动态代理是基于接口实现的,所以我们先定义一个接口 public interface Executer { public Object execut ...
- java:struts框架2(方法的动态和静态调用,获取Servlet API三种方式(推荐IOC(控制反转)),拦截器,静态代理和动态代理(Spring AOP))
1.方法的静态和动态调用: struts.xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCT ...
- aop学习总结二------使用cglib动态代理简单实现aop功能
aop学习总结二------使用cglib动态代理简单实现aop功能 模拟业务需求: 1.拦截所有业务方法 2.判断用户是否有权限,有权限就允许用户执行业务方法,无权限不允许用户执行业务方法 (判断是 ...
- java中代理,静态代理,动态代理以及spring aop代理方式,实现原理统一汇总
若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的. 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类. ...
- 【Java EE 学习 51】【Spring学习第三天】【cglib动态代理】【AOP和动态代理】【切入点表达式】
一.cglib动态代理 1.简介 (1)CGlib是一个强大的,高性能,高质量的Code生成类库.它可以在运行期扩展Java类与实现Java接口. (2) 用CGlib生成代理类是目标类的子类. (3 ...
- 动态代理模式和AOP探究
java强大的反射机制给动态代理带来了可能.能够自由穿梭在类与方法之间.简直神通广大. 动态代理的一个小例子,顺便看看神奇的AOP是如何实现的.代码如下: 首先声明的是一个接口Dog类 package ...
- 从动态代理到Spring AOP(中)
一.前言 上一章节主要介绍了JDK动态代理和CGLIB动态代理:https://www.cnblogs.com/GrimMjx/p/11194283.html 这一章主要结合我们之前学习的动态代理的基 ...
- java使用动态代理来实现AOP(日志记录)
以下内容为原创,转载时请注明链接地址:http://www.cnblogs.com/tiantianbyconan/p/3336627.html AOP(面向方面)的思想,就是把项目共同的那部分功能分 ...
- .NET 自带的动态代理+Expression 实现AOP
下面代码(摘抄之别处,原创在哪不知)是采用TransparentProxy和RealProxy实现对象的动态代理.碍于其使用反射掉用方法,所以就小试着将反射改成Expression以提高执行的效率.第 ...
随机推荐
- JAVA+FlexPaper+OpenOffice+SWFTools文档预览
http://blog.csdn.net/core_star/article/details/10148047 1.软件环境: openoffice:启动openoffice服务:soffice.ex ...
- 看完《Don't make me think》的总结
寒假在公司实习,然后公司人数比较少,作为一个前端实习生,分工下,就去负责了项目的业务逻辑的梳理以及页面的设计,为了让页面设计的好看,交互性好,便于用户使用,我就快速看了这本薄薄的却很有用的书.书的整体 ...
- iOS- 自定义UIView (测试block和代理)
#import <UIKit/UIKit.h> typedef void(^compeletionHandler) (NSInteger selectButtonIndex); @clas ...
- javass 视频笔记二 (关键字,标示符,常量变量,运算符和if-else)
1,java的关键字和标识符2,java的基本数据类型3,变量和常量4,java的运算符5,if-else if - else表达式1,java的关键字和标识符 1.1,所有关键字都要小写 ...
- iOS 10 的一些资料整理
文/判若两人丶(简书作者)原文链接:http://www.jianshu.com/p/0cc7aad638d9 1.iOS 10 隐私权限设置 iOS 10 开始对隐私权限更加严格,如果你不设置就会直 ...
- Django中创建自己的Context_Processors
在settings.py中有一个变量TEMPLATE_CONTEXT_PROCESSORS 一般它担任对我们的模板页面与环境进行处理解析的过程 比如原来默认的django不能在template中使 ...
- 《Cortex-M0权威指南》之体系结构---存储器系统
转载请注明来源:cuixiaolei的技术博客 Cortex-M0处理器为32位处理器,所以具有最大4G的寻址空间.在体系结构上,存储器空间被划分位一系列的区域,每个区域都有推荐的用途,以提高不同设备 ...
- Uva 10305 - Ordering Tasks 拓扑排序基础水题 队列和dfs实现
今天刚学的拓扑排序,大概搞懂后发现这题是赤裸裸的水题. 于是按自己想法敲了一遍,用queue做的,也就是Kahn算法,复杂度o(V+E),调完交上去,WA了... 于是检查了一遍又交了一发,还是WA. ...
- springMVC+hibernate构建项目
这几天要用到springMVC+spring+hibernate构建框架,使用的是eclipse今天闲下来把这些记录下来 首先要导入spring 的jar包和hibernate的jar包
- Java程序员必备的 15框开发工具
15款Java程序员必备的开发工具 如果你是一名Web开发人员,那么用膝盖想也知道你的职业生涯大部分将使用Java而度过.这是一款商业级的编程语言,我们没有办法不接触它. 对于Java,有两种截然不同 ...