其实说起AOP,我在2011年的时候就发过一个帖子,CSDN的地址为http://bbs.csdn.net/topics/370067862,只是那时候对EMIT了解的深度不够,所以内容显得有些稚嫩,但对于我来说,意义很大。从那个时候开始起我算对EMIT入门了。
不扯远了,回到正题上来。AOP的实现方式是分2种的,一种是继承式的,这种实现的方式需要注入的方法上打上virtual,这样子类才能继承并重写它,如下图所示:
第二种就是代理式的,代理式的注入一般是需要有抽象的接口的,其大致的实现原理如下图所示:
而本文所使用的方式就是第二种,这里可能有的童鞋有疑问了,为啥呢?这里说明一下,在方法内部的EMIT代码的植入上其实没什么区别,只是第一种方式只需要重写带virtual的方法即可,在EMIT上而言,较为简单,并且在2011年的那个帖子的实现方式就是基于第一种,所以这次想换条路走走。而第二种是需要一个对接口实现的过程,难度稍微大一些,从学习的角度,自然也是最佳的选择。
说到这里只交代了正题的一半,那另一半是怎么回事呢?刚才已经把代理式的AOP的原理大致的说了一下,最终会动态的创建一个实现了某个接口的类,既然费劲的创建了一个新类,那肯定就是要使用它来做事情,做事情的第一步是什么呢?对拉,就是new一个实例。这时候懒人(例如我)就说了,这一个个的new多费劲,而且代码显得很low,想高大上?这时候你是不是想到了IOC或者DI呢(这俩名词不理解的童鞋可自行BAIDU),是的,可以。但一想到自己一个小小的项目要引一堆的dll,而且还用不到里面的几个方法,于是我创造轮子的想法又蹦出来了,当前这个不能跟各种IOC框架或者DI框架比,不是一个量级,也比不上人家完美,但对于我来说,就仅仅需要它自动装配即可,够用就好。于是在实现了AOP的基础上,自动装配的代码也开动了。。。
原理上我们大概了解了,剩下的就是动手了,而动手其实就是烧脑的过程,各种头疼的IL指令,为了不让各位童鞋也头疼或者看的费劲,这里面的过程我就不做详细的解释了,贴几个能展现部分逻辑的重要代码段:
最后我想通过一些测试的代码来展示一下这个东西的最终的效果,如果有想研究EMIT的童鞋,可根据我代码里面的注释,以及各种IL指令去理解和尝试一下自己创造一个轮子。
测试代码中测试了AOP的三种拦截方式:
1、一般拦截,在方法执行的前后,各执行一段代码
2、认证拦截,只有通过了认证接口后,才能正常的调用代理类的方法
3、异常拦截,在出现异常时,进行异常的捕获与处理
对测试类打的标记如下图所示:
写的测试例子:
运行的结果:
写到这里也就结束了,由于文采有限,只是把我想说的重点,表述了一下,大部分的内容都是贴图,可能有部分的童鞋看的不习惯,还请轻喷,谢谢。
关于版权,由于我的知识来自互联网,可以说,没有互联网,就没有现在的我,甚至就没我现在的饭碗,本着感恩的心,诚挚的回馈。所以我这里的代码是完全公开的,不涉及版权,您可以随便用(如果您对本源码有改造或者扩展,而且您愿意与大家一起分享的话,我将不胜感激),但因此而产生的各种后果也请您自行承担。如果您要转载本文,还请您保留原文的地址,谢谢。
源码地址:http://download.csdn.net/detail/nqicecoffee/9592036
=======================================2016年8月3日更新===============================================
经过高人 @时光之后 指点后,修正了2处问题:
1、修复属性的植入逻辑
2、优化初始化结果的IL指令
源码地址:http://download.csdn.net/detail/nqicecoffee/9593358