一.   什么是AOP:

a)         AOP是面向切面编程; 就像oop一样, 它也是一种编程思想;

i.    Oop思想→一切皆对象, 对象交互组成功能, 功能叠加组成模块, 模块叠加组成系统; 如果把一个个的类比喻成一个个砖头, 那么系统就是一个房子; 房子是由一块块砖头构成, 所以面向对象非常适合做大型系统; 但是面向对象的在应对系统扩展的时候, 就显得力不从心; 如果砖块需要发生变化, 则就会牵扯到很多地方; 因为面向对象是静态的, 内部就是强耦合的关系; 虽然设计模式可以解决这些问题中的某些部分, 比如可以创建出可扩展, 可重用的架构, 但是设计模式操作的最小单元也是类(砖头), 无法解决类的内部的变化

ii.   AOP→面向切面编程, 是对OOP的补充; 主要功能就是为了解决类的内部变化, 在不破坏类封装的同时, 水平扩展类的功能; 降低模块间的耦合度; 注意AOP不是实现业务行为的: 比如一个People类, 本身具有跑步, 吃饭, 睡觉这三个方法, 但是如果你想通过AOP为其增加一个 游泳 的方法, 那么AOP就不适用了; 因为这种属于业务层面, 在封装类的时候, 就应该存在的行为; AOP主要是用来做一些通用的功能, 比如 权限校验/日志记录/发送消息/缓存处理/性能监控 等等一些通用的非业务逻辑的功能;

iii.    总结:

    1. 所以说AOP 只是对OOP思想的一种补充, 解决类的内部通用功能的变化
    2. 所有的业务功能还是由OOP来实现, 比如People类需要增加 游泳 方法, 还是得有OOP来完成
    3. 有了AOP之后, OOP的实现也变得简单了, 因为OOP的代码, 只用关注业务逻辑; 无需再操心各种通用的功能了

二. 利用装饰器模式实现简答的AOP, 没有通用性:

a)         实现代码:

  1. /// <summary>
  2. /// 1. 这个接口定义一个注册用户的行为
  3. /// </summary>
  4. public interface IUserProcessor
  5. {
  6. void RegUser(User user);
  7. }
  8.  
  9. /// <summary>
  10. /// 2. 普通的实现
  11. /// </summary>
  12. public class UserProcessor : IUserProcessor
  13. {
  14. public void RegUser(User user)
  15. {
  16. Console.WriteLine("用户已注册。Name:{0},PassWord:{1}", user.Name, user.Password);
  17. }
  18. }
  19.  
  20. /// <summary>
  21. /// 3. 利用装饰器模式的实现, 这个就类似于简单的AOP功能,
  22. /// 装饰器即实现了IuserProcessor的接口
  23. /// 但在实现的同时, 还组合进一个IuserProcessor对象;
  24. /// 这就是一个标准的装饰器模式
  25. /// </summary>
  26. public class UserProcessorDecorator : IUserProcessor
  27. {
  28. //组合一个IUserProcessor对象
  29. private IUserProcessor _UserProcessor { get; set; }
  30. public UserProcessorDecorator(IUserProcessor userprocessor)
  31. {
  32. this._UserProcessor = userprocessor;
  33. }
  34. //实现接口
  35. public void RegUser(User user)
  36. {
  37. BeforeProceed(user);
  38.  
  39. this._UserProcessor.RegUser(user);
  40.  
  41. AfterProceed(user);
  42. }
  43.  
  44. /// <summary>
  45. /// 定义在业务逻辑执行之前要执行的动作
  46. /// </summary>
  47. /// <param name="user"></param>
  48. private void BeforeProceed(User user)
  49. {
  50. Console.WriteLine("方法执行前");
  51. }
  52. /// <summary>
  53. /// 定义在业务逻辑执行之后要执行的动作
  54. /// </summary>
  55. /// <param name="user"></param>
  56. private void AfterProceed(User user)
  57. {
  58. Console.WriteLine("方法执行后");
  59. }
  60. }

b) 调用

  1. public static void Show()
  2. {
  3. User user = new User()
  4. {
  5. Name = "孙悟空",
  6. Password = "123456"
  7. };
  8.  
  9. //5. 装饰器模式使用的方法
  10. IUserProcessor processor = new UserProcessor();
  11. processor.RegUser(user); //普通实现
  12.  
  13. Console.WriteLine("***************");
  14.  
  15. user = new User()
  16. {
  17. Name = "八戒AOP",
  18. Password = "567890"
  19. };
  20. processor = new UserProcessorDecorator(processor);
  21. processor.RegUser(user);//使用装饰器模式实现的AOP, 看起来只为此类的此方法单独实现的, 有很大局限性
  22. }

c)  执行结果截图:

三.  使用.net Remoting实现动态代理(AOP), 不太推荐, .net Remoting对父类的限制实在是太大了

a)         创建一个接口, 这里和装饰器模式没有什么区别

  1. /// <summary>
  2. /// 1. 使用.net Remoting 来实现动态代理, 这里的业务还是和装饰器与代理模式的业务一样
  3. /// </summary>
  4. public interface IUserProcessor
  5. {
  6. void RegUser(User user);
  7. }

b)  实现接口, 并继承MarshalByRefObject

  1. /// <summary>
  2. /// 必须继承自MarshalByRefObject父类,否则无法生成;
  3. /// 这个继承就感觉比较恶心了;因为C#中都是单继承的
  4. ///
  5. /// 2. 定义一个UserProcessor来实现IUserProcessor, 必须继承一个MarshalByRefObject; 继承此类是.net Remoting的固定写法类; 如果想实现动态代理就必须继承这个类(MarshalByRefObject)
  6. /// </summary>
  7. public class UserProcessor : MarshalByRefObject, IUserProcessor
  8. {
  9. public void RegUser(User user)
  10. {
  11. Console.WriteLine("用户已注册。用户名称{0} Password{1}", user.Name, user.Password);
  12. }
  13. }

c)  使用Remoting进行对象生成的动态代理的固定写法

  1. /// <summary>
  2. /// MyRealProxy<T> 就是真实代理, 这个类里面的东西, 属于固定写法, 是.net Remoting封装好的
  3. /// </summary>
  4. /// <typeparam name="T"></typeparam>
  5. public class MyRealProxy<T> : RealProxy
  6. {
  7. private T tTarget;
  8. public MyRealProxy(T target): base(typeof(T))
  9. {
  10. this.tTarget = target;
  11. }
  12.  
  13. /// <summary>
  14. /// .net Remoting的核心方法
  15. /// </summary>
  16. /// <param name="msg"></param>
  17. /// <returns></returns>
  18. public override IMessage Invoke(IMessage msg)
  19. {
  20. BeforeProceede(msg); //在执行方法之前做一些其它自定义的动作
  21.  
  22. //这里执行真实的方法体, 在这个方法体之前(之后)都可以加一点自己的动作
  23. IMethodCallMessage callMessage = (IMethodCallMessage)msg;
  24. object returnValue = callMessage.MethodBase.Invoke(this.tTarget, callMessage.Args);
  25.  
  26. AfterProceede(msg);//在执行方法之后执行一些其它动作
  27.  
  28. return new ReturnMessage(returnValue, new object[0], 0, null, callMessage);
  29. }
  30. #region 可以扩展的逻辑
  31. public void BeforeProceede(IMessage msg)
  32. {
  33. Console.WriteLine("方法执行前可以加入的逻辑");
  34. }
  35. public void AfterProceede(IMessage msg)
  36. {
  37. Console.WriteLine("方法执行后可以加入的逻辑");
  38. }
  39. #endregion
  40. }
  41. /// <summary>
  42. /// 透明代理; 固定的写法, 表示如何使用.net Remoting来生成对象
  43. /// </summary>
  44. public static class TransparentProxy
  45. {
  46. public static T Create<T>()
  47. {
  48. //使用反射动态创建对象
  49. T instance = Activator.CreateInstance<T>();
  50. //将对象包装一层, 交给MyRealProxy
  51. MyRealProxy<T> realProxy = new MyRealProxy<T>(instance);
  52. //GetTransparentProxy→父类的方法
  53. T transparentProxy = (T)realProxy.GetTransparentProxy();
  54. return transparentProxy;
  55. }
  56. }

d) 调用方法:

  1. public static void Show()
  2. {
  3. User user = new User()
  4. {
  5. Name = "孙悟空",
  6. Password = "123456"
  7. };
  8.  
  9. UserProcessor processor = new UserProcessor();
  10. processor.RegUser(user);
  11. Console.WriteLine("*********************");
  12.  
  13. user = new User()
  14. {
  15. Name = "八戒AOP",
  16. Password = "567890"
  17. };
  18. //利用TransparentProxy来创建对象
  19. UserProcessor userProcessor = TransparentProxy.Create<UserProcessor>();
  20. //调用RegUser时, 会进入到Invoke方法中, 至于为什么会进入到Invoke中, 是由.net Remoting的底层来实现的
  21. userProcessor.RegUser(user);
  22. }

e)         执行结果:

四.   使用Castle实现动态代理

   对于Castle来说, 实现接口时, 方法必须是一个虚方法; 主要代码如下:

  1. /// <summary>
  2. /// 使用Castle\DynamicProxy 实现动态代理
  3. /// 方法必须是虚方法
  4. /// </summary>
  5. public class CastleProxyAOP
  6. {
  7. /// <summary>
  8. /// 1. 业务和动态代理/装饰器模式/.net Remoting(RealProxy)都是一样, 定义接口对象
  9. /// </summary>
  10. public interface IUserProcessor
  11. {
  12. void RegUser(User user);
  13. }
  14.  
  15. /// <summary>
  16. /// 2. 业务子类实现IUserProcessor接口
  17. /// </summary>
  18. public class UserProcessor : IUserProcessor
  19. {
  20. /// <summary>
  21. /// 必须带上virtual 否则无效
  22. /// </summary>
  23. /// <param name="user"></param>
  24. public virtual void RegUser(User user)
  25. {
  26. Console.WriteLine($"用户已注册。Name:{user.Name},PassWord:{user.Password}");
  27. }
  28. }
  29.  
  30. /// <summary>
  31. /// 3. 这里是个重点, Intercept()方法是个重点
  32. /// </summary>
  33. public class MyInterceptor : IInterceptor
  34. {
  35. public void Intercept(IInvocation invocation)
  36. {
  37. //在方法调用之前执行的动作
  38. PreProceed(invocation);
  39. invocation.Proceed(); //这里是真实的方法调用
  40. //在方法调用之后执行的动作
  41. PostProceed(invocation);
  42. }
  43. public void PreProceed(IInvocation invocation)
  44. {
  45. Console.WriteLine("方法执行前");
  46. }
  47.  
  48. public void PostProceed(IInvocation invocation)
  49. {
  50. Console.WriteLine("方法执行后");
  51. }
  52. }
  53.  
  54. public static void Show()
  55. {
  56. User user = new User()
  57. {
  58. Name = "孙悟空",
  59. Password = "456789"
  60. };
  61.  
  62. //4. 调用
  63. ProxyGenerator generator = new ProxyGenerator();
  64. MyInterceptor interceptor = new MyInterceptor();
  65.  
  66. //5. 创建对象; (这个也是动态实现的AOP); 固定写法
  67. // 基于里式替换原则,右边是父类, 那么在调用的时候, 根本就不会去管左边是个什么, 直接会调用父类的RegUser方法, 如果要调用子类的RegUser方法, 则必须标注virtual
  68. UserProcessor userprocessor = generator.CreateClassProxy<UserProcessor>(interceptor);
  69. userprocessor.RegUser(user);
  70. }
  71.  
  72. }

  

20181122_C#中AOP初探_装饰器模式的AOP_Remoting实现AOP_Castle实现AOP的更多相关文章

  1. 聊聊模板方法模式,装饰器模式以及AOP

    在软件系统设计的时候,我们需要把一个大的系统按照业务功能进行拆分,做到高内聚.低耦合. 但是呢,拆分之后会产生一些通用性的东西,比如日志,安全,事务,性能统计等,这些非功能性需求,横跨多个模块.最lo ...

  2. 2.静态AOP实现-装饰器模式

    通过装饰器模式实现在RegUser()方法本身业务前后加上一些自己的功能,如:BeforeProceed和AfterProceed,即不修改UserProcessor类又能增加新功能 定义1个用户接口 ...

  3. java设计模式之装饰器模式以及在java中作用

    在JAVA I/O类库里有很多不同的功能组合情况,这些不同的功能组合都是使用装饰器模式实现的,下面以FilterInputStream为例介绍装饰器模式的使用  FilterInputStream和F ...

  4. JS 设计模式九 -- 装饰器模式

    概念 装饰者(decorator)模式能够在不改变对象自身的基础上,动态的给某个对象添加额外的职责,不会影响原有接口的功能. 模拟传统面向对象语言的装饰者模式 //原始的飞机类 var Plane = ...

  5. 装饰器模式(Decorator)

    一.装饰模式介绍 装饰模式(decorator):表示动态的给一个对象添加一些新的功能(利用子类继承父类也可以实现),但是比生成子类方式更灵活. 也叫装饰者模式或者装饰器模式 例如:我们每个人身上穿的 ...

  6. Python设计模式-装饰器模式

    装饰器模式 装饰器模式,动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式比生成子类更为灵活. 代码示例 #coding:utf-8 #装饰器模式 class Beverage():   ...

  7. 重学 Java 设计模式:实战装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 对于代码你有编程感觉吗 很多人写代码往往是没有编程感觉的,也就是除了可以把功能按照固 ...

  8. PHP 装饰器模式

    装饰器模式:是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能. [装饰器模式中主要角色] 抽象组件角色(Component):定义一个对象接口,以规范准备接受附加责任的对象,即可以给这 ...

  9. 设计模式-装饰器模式(Decrator Model)

    文 / vincentzh 原文连接:http://www.cnblogs.com/vincentzh/p/6057666.html 目录 1.概述 2.目的 3.结构组成 4.实现 5.总结 1.概 ...

随机推荐

  1. asp.net设置gridview页码显示遇到的问题

    问题:分页部分显示的页码撑开占满整个表格底部 解决方法: 1.通过浏览器察看源,发现是分页部分的table样式受到整个页面的table设置的样式的影响,分页是一个tr里面的td里面的table 2.设 ...

  2. jsp笔记总结

    第一章 JavaWeb简介 1.什么是Web应用程序 什么是Web应用程序是一种通过Web访问的应用程序.Web应用程序一个最大优点就是用户很容易访问.用户只需要有浏览器即可,不需要再安装其他软件.W ...

  3. 测试实战经验之checklist篇20140905

    我们测试中,在各个环节应该有自己的一个checklis来帮助我们梳理我们要做什么,该做什么,以下是我的一个小总结: 1.在测试前我们需要做的: 2.在拿到测试包后我们该做的 3.测试通过后我们该做的 ...

  4. PHP中cookies跨目录无法调用

    <?php  setcookie("messagetime",time(),time()+60);  ?> 写法无法跨目录调用呢.在搜索引擎中搜索,并没有找到答案(可能 ...

  5. 快速生成树RTSP

    Note: 数据分组:

  6. JSCover(查看代码覆盖率)

    1. [文档](http://tntim96.github.io/JSCover/manual/manual.xml)1. [下载](https://sourceforge.net/projects/ ...

  7. I.MX6 Kernel BUG at include/linux/netdevice.h:520!

    /*************************************************************************** * I.MX6 Kernel BUG at i ...

  8. BZOJ1833 ZJOI2010 count 数字计数 【数位DP】

    BZOJ1833 ZJOI2010 count 数字计数 Description 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. Input 输入文件中仅包 ...

  9. Nginx+phpfastcgi下flush 一下子全部输出问题

    最近由于业务需要,需要使用php的flush输出缓存刷新,处理浏览器超时问题. 最初的测试代码如下: ob_start();//打开缓冲区for ($i=10; $i>0; $i--){ ech ...

  10. 关于上架AppStore最后一步的“出口合规信息”、“内容版权”、“广告标识符”的选择(转)

    这里只当作记录:http://blog.csdn.net/ashimar_a/article/details/51745675