aop的原理探究
前言
aop的概念时常提起, 但是没有在实际场景中使用, 最近有机会在实际场景中运用, 这里深入的记录一下探索过程.
aop 的分类
aop 全称: Aspect Oriented Programming , 即面向切面编程, 是在编译时或者运行时为某一个切点(一般是方法)添加统一的功能的一种编码方式.
编译时AOP(静态织入), 常见的框架 PostSharp(主流用法, 基于mono.cicel + MSbuild, 也可以运行时AOP)
运行时AOP(动态代理), 常见框架 Castle, 主流 IOC 框架实现代理
编译时AOP
根据名称可以知道, 这个过程发生在dll编译的时候. 编译时AOP是将织入的方法通过IL的方式直接写入编译的dll中. 这一点通过反编译postsharp 等工具的生成dll 可知
优点: 整体效率比运行时要高, 功能强大.
缺点: 修改代码需要重新通过专门的编译器编译, 操作相对复杂.
运行时AOP
通常使用系统自带的反射机制或者第三方IOC框架在运行时动态执行需要织入的方法.
优点: 核心思想和使用都比较简单
缺点: 性能略低, 一般只适合方法的调用.
下面使用.net Remoting 来实现一个简单的 aop 功能
static void Main(string[] args)
{
var service = TinyAop.Create<IServiceA, ServiceA>(new LogInterceptor(), new ErrorInterceptor());
service.Say("hello world");
service.Error();
Console.Read();
}
interface IServiceA { void Say(string word); void Error(); }
public class ServiceA : IServiceA
{
public void Error()
{
throw new Exception("出错啦");
}
public void Say(string word)
{
Console.WriteLine(word);
}
}
class LogInterceptor : Interceptor
{
public void Invoke(Invocation invocation)
{
try
{
Console.WriteLine("before log");
invocation.Proceed();
Console.WriteLine("after log");
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
invocation.ReturnValue = "出错啦";
}
}
}
class ErrorInterceptor : Interceptor
{
public void Invoke(Invocation invocation)
{
try
{
invocation.Proceed();
}
catch (Exception ex)
{
invocation.ReturnValue = "出错啦";
Console.WriteLine(ex.InnerException);
}
}
}
class TinyAop
{
public static T Create<IT, T>(params Interceptor[] interceptors)
{
T instance = Activator.CreateInstance<T>();
RealProxyEx<T> realProxy = new RealProxyEx<T>(instance, interceptors);
T transparentProxy = (T)realProxy.GetTransparentProxy();
return transparentProxy;
}
}
class RealProxyEx<T> : RealProxy
{
private object _target;
private Interceptor[] _interceptors;
public RealProxyEx(object target, Interceptor[] interceptors) : base(typeof(T))
{
_target = target;
_interceptors = interceptors;
}
public override IMessage Invoke(IMessage msg)
{
Invocation invocation = new Invocation(msg, _target);
if (_interceptors != null && _interceptors.Length > 0)
{
foreach (var item in _interceptors)
{
item.Invoke(invocation);
}
}
else
{
invocation.Proceed();
}
return new ReturnMessage(invocation.ReturnValue, new object[0], 0, null, invocation.CallMessage);
}
}
class Invocation
{
public MethodBase Method { get; set; }
public object ReturnValue { get; set; }
public IMethodCallMessage CallMessage => (IMethodCallMessage)_msg;
private IMessage _msg;
private object _target;
public Invocation(IMessage msg, object target)
{
_target = target;
_msg = msg;
}
public void Proceed()
{
IMethodCallMessage callMessage = (IMethodCallMessage)_msg;
Method = callMessage.MethodBase;
ReturnValue = Method.Invoke(_target, callMessage.Args);
}
}
interface Interceptor
{
void Invoke(Invocation invocation);
}
隔壁spring框架中的类比
编译时: AspectJ
运行时: jdk(一般代理接口), cglib (代理(重写)实现类)
总结
AOP的思想比如何使用更重要, 仔细学习看看, 其实很简单.
代码托管地址
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 zhao4xi@126.com
文章标题:aop的原理探究
文章字数:693
本文作者:Zhaoxi
发布时间:2019-09-17, 21:12:58
最后更新:2019-09-18, 21:15:13
原始链接:http://zhao4xi.github.io/2019/09/17/aop的原理探究/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。