aop的原理探究

  1. 前言
  2. aop 的分类
  3. 编译时AOP
  4. 运行时AOP
  5. 隔壁spring框架中的类比
  6. 总结
    1. 代码托管地址

前言

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" 转载请保留原文链接及作者。

目录