一.   什么是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)         实现代码:

/// <summary>
/// 1. 这个接口定义一个注册用户的行为
/// </summary>
public interface IUserProcessor
{
void RegUser(User user);
} /// <summary>
/// 2. 普通的实现
/// </summary>
public class UserProcessor : IUserProcessor
{
public void RegUser(User user)
{
Console.WriteLine("用户已注册。Name:{0},PassWord:{1}", user.Name, user.Password);
}
} /// <summary>
/// 3. 利用装饰器模式的实现, 这个就类似于简单的AOP功能,
/// 装饰器即实现了IuserProcessor的接口
/// 但在实现的同时, 还组合进一个IuserProcessor对象;
/// 这就是一个标准的装饰器模式
/// </summary>
public class UserProcessorDecorator : IUserProcessor
{
//组合一个IUserProcessor对象
private IUserProcessor _UserProcessor { get; set; }
public UserProcessorDecorator(IUserProcessor userprocessor)
{
this._UserProcessor = userprocessor;
}
//实现接口
public void RegUser(User user)
{
BeforeProceed(user); this._UserProcessor.RegUser(user); AfterProceed(user);
} /// <summary>
/// 定义在业务逻辑执行之前要执行的动作
/// </summary>
/// <param name="user"></param>
private void BeforeProceed(User user)
{
Console.WriteLine("方法执行前");
}
/// <summary>
/// 定义在业务逻辑执行之后要执行的动作
/// </summary>
/// <param name="user"></param>
private void AfterProceed(User user)
{
Console.WriteLine("方法执行后");
}
}

b) 调用

public static void Show()
{
User user = new User()
{
Name = "孙悟空",
Password = "123456"
}; //5. 装饰器模式使用的方法
IUserProcessor processor = new UserProcessor();
processor.RegUser(user); //普通实现 Console.WriteLine("***************"); user = new User()
{
Name = "八戒AOP",
Password = "567890"
};
processor = new UserProcessorDecorator(processor);
processor.RegUser(user);//使用装饰器模式实现的AOP, 看起来只为此类的此方法单独实现的, 有很大局限性
}

c)  执行结果截图:

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

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

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

b)  实现接口, 并继承MarshalByRefObject

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

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

/// <summary>
/// MyRealProxy<T> 就是真实代理, 这个类里面的东西, 属于固定写法, 是.net Remoting封装好的
/// </summary>
/// <typeparam name="T"></typeparam>
public class MyRealProxy<T> : RealProxy
{
private T tTarget;
public MyRealProxy(T target): base(typeof(T))
{
this.tTarget = target;
} /// <summary>
/// .net Remoting的核心方法
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public override IMessage Invoke(IMessage msg)
{
BeforeProceede(msg); //在执行方法之前做一些其它自定义的动作 //这里执行真实的方法体, 在这个方法体之前(之后)都可以加一点自己的动作
IMethodCallMessage callMessage = (IMethodCallMessage)msg;
object returnValue = callMessage.MethodBase.Invoke(this.tTarget, callMessage.Args); AfterProceede(msg);//在执行方法之后执行一些其它动作 return new ReturnMessage(returnValue, new object[0], 0, null, callMessage);
}
#region 可以扩展的逻辑
public void BeforeProceede(IMessage msg)
{
Console.WriteLine("方法执行前可以加入的逻辑");
}
public void AfterProceede(IMessage msg)
{
Console.WriteLine("方法执行后可以加入的逻辑");
}
#endregion
}
/// <summary>
/// 透明代理; 固定的写法, 表示如何使用.net Remoting来生成对象
/// </summary>
public static class TransparentProxy
{
public static T Create<T>()
{
//使用反射动态创建对象
T instance = Activator.CreateInstance<T>();
//将对象包装一层, 交给MyRealProxy
MyRealProxy<T> realProxy = new MyRealProxy<T>(instance);
//GetTransparentProxy→父类的方法
T transparentProxy = (T)realProxy.GetTransparentProxy();
return transparentProxy;
}
}

d) 调用方法:

public static void Show()
{
User user = new User()
{
Name = "孙悟空",
Password = "123456"
}; UserProcessor processor = new UserProcessor();
processor.RegUser(user);
Console.WriteLine("*********************"); user = new User()
{
Name = "八戒AOP",
Password = "567890"
};
//利用TransparentProxy来创建对象
UserProcessor userProcessor = TransparentProxy.Create<UserProcessor>();
//调用RegUser时, 会进入到Invoke方法中, 至于为什么会进入到Invoke中, 是由.net Remoting的底层来实现的
userProcessor.RegUser(user);
}

e)         执行结果:

四.   使用Castle实现动态代理

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

/// <summary>
/// 使用Castle\DynamicProxy 实现动态代理
/// 方法必须是虚方法
/// </summary>
public class CastleProxyAOP
{
/// <summary>
/// 1. 业务和动态代理/装饰器模式/.net Remoting(RealProxy)都是一样, 定义接口对象
/// </summary>
public interface IUserProcessor
{
void RegUser(User user);
} /// <summary>
/// 2. 业务子类实现IUserProcessor接口
/// </summary>
public class UserProcessor : IUserProcessor
{
/// <summary>
/// 必须带上virtual 否则无效
/// </summary>
/// <param name="user"></param>
public virtual void RegUser(User user)
{
Console.WriteLine($"用户已注册。Name:{user.Name},PassWord:{user.Password}");
}
} /// <summary>
/// 3. 这里是个重点, Intercept()方法是个重点
/// </summary>
public class MyInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
//在方法调用之前执行的动作
PreProceed(invocation);
invocation.Proceed(); //这里是真实的方法调用
//在方法调用之后执行的动作
PostProceed(invocation);
}
public void PreProceed(IInvocation invocation)
{
Console.WriteLine("方法执行前");
} public void PostProceed(IInvocation invocation)
{
Console.WriteLine("方法执行后");
}
} public static void Show()
{
User user = new User()
{
Name = "孙悟空",
Password = "456789"
}; //4. 调用
ProxyGenerator generator = new ProxyGenerator();
MyInterceptor interceptor = new MyInterceptor(); //5. 创建对象; (这个也是动态实现的AOP); 固定写法
// 基于里式替换原则,右边是父类, 那么在调用的时候, 根本就不会去管左边是个什么, 直接会调用父类的RegUser方法, 如果要调用子类的RegUser方法, 则必须标注virtual
UserProcessor userprocessor = generator.CreateClassProxy<UserProcessor>(interceptor);
userprocessor.RegUser(user);
} }

  

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. 记用ajax网页跳转大坑——后台执行了,但是没有跳转

    搭建javaweb服务器的时候,把jsp文件放在WEB-INF目录下面,因为超链接不能所有只能通过拦截器,用do方法跳转 controller写的是对的: @Controller public cla ...

  2. New Concept English three(11)

    Customs Officers are quite tolerant these days, but they can still stop you when you are going throu ...

  3. PostgreSQL copy命令使用记录

    上篇写到用pg_bulkload来导入数据,但是实际的环境是solaris,pg_bulkload还不支持,于是用copy的方式,下面附上脚本 -bash-4.1$ cat copy.sh #!/bi ...

  4. 虚拟机中centos7与物理主机通讯

    本地物理机 WIN命令行:ipconfig 查看网络配置 在物理机的网络配置--> 配置VMnet8 打开VMware  编辑虚拟机设置,选择自定义NAT模式(VMnat8) 编辑->虚拟 ...

  5. MongoDB使用笔记

    先创建目录,创建log文件,然后启动服务 cd /d D:\Program Files\MongoDB\Server\3.4\bin\ mongod.exe --dbpath d:\data\db - ...

  6. 02-C与OC语言的一些小知识

    1.        #import 跟#include.@class有什么区别?#import<> 跟 #import”"又什么区别? 1>  #import和#inclu ...

  7. vue中使用less

    我们需要下载less对应的依赖包 第一步: 安装less依赖,npm install less less-loader --save 第二步: 修改webpack.config.js文件,配置load ...

  8. java并发--Callable、Future和FutureTask

    在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果. 如果需要获取执行结果,就 ...

  9. pat甲级 1154 Vertex Coloring (25 分)

    A proper vertex coloring is a labeling of the graph's vertices with colors such that no two vertices ...

  10. c#代码加密

    源代码保护:怎样利用MaxtoCode加密dotNet源代码 http://www.webkaka.com/blog/archives/MaxtoCode-encrypt-dotnet-program ...