20181122_C#中AOP初探_装饰器模式的AOP_Remoting实现AOP_Castle实现AOP

一.   什么是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);
        } 

    }

  

原文地址:https://www.cnblogs.com/wxylog/p/10000228.html

时间: 2024-10-10 00:48:48

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

设计模式(三)_装饰器模式

上篇学习了策略模式,现在回想下,什么是策略模式,好了.本篇主要介绍装饰器模式,just do it! 什么是装饰器模式 装饰器模式指的是动态的将责任附加到对象上.若要扩展功能,装饰器模式提供了比继承更弹性的替代方案. 如何使用装饰器模式 老王来到商场买衣服,需要买衣服,裤子,帽子...... public class Wang { public void show(){ System.out.println("我穿上衣服,累计花费100元"); System.out.println(&

10.9-全栈Java笔记:装饰器模式构建IO流体系

装饰器模式 装饰器模式是GOF23种设计模式中较为常用的一种模式.它可以实现对原有类的包装和装饰,使新的类具有更强的功能. 我这里有智能手机Iphone, 我们可以通过加装投影组件,实现原有手机功能的扩展.这就是一种"装饰器模式". 我们在未来普通人加装"外骨骼"装饰,让普通人具有力扛千斤的能力,也是一种"装饰器模式". [图] 手机经过投影套件"装饰后",成为功能更强的"投影手机" [示例1]装饰器模式代

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

在JAVA I/O类库里有很多不同的功能组合情况,这些不同的功能组合都是使用装饰器模式实现的,下面以FilterInputStream为例介绍装饰器模式的使用  FilterInputStream和FilterOutputStream 首先,这两个都分别是InputStream和OutputStream的子类.而且,FilterInputStream和FilterOutputStream是具体的子类,实现了InputStream和OutputStream这两个抽象类中为给出实现的方法. 但是,F

IO中的装饰器模式

//可以进InputStream 类 区分为目的和方法两类 //一般直接子类,都是目的不同的(A类), // 如FileInputStream, #从文件中获得字节.// ByteArrayInputStream #包含一个内存缓冲区,字节从中取出.// ObjectInputStream #用来恢复被序列化的对象.// PipedInputStream #管道输入流,读取管道内容.多和PipedOutputStream一起用于多线程通信.// SequenceInputStream #是多种输

设计模式篇——初探装饰器模式

文章目录 1.装饰器模式介绍 2.装饰器模式类图 3.装饰器模式Demo实现(一个小镇的拉面馆) 4.装饰器模式总结 装饰器模式介绍:装饰器模式可以在不修改任何底层代码的情况下,给对象赋予新的职责(程序运行时的扩展,动态的将责任附加到对象上).属于结构型设计模式. 类图: 我们来看下装饰器模式的类图: 一个简单的Demo(故乡小镇的一个面馆): 在故乡的一个小镇上面,有一家面馆,主营拉面.在这里你可以只点清汤面(SoupNoodle),也可以往里面加佐料,佐料有牛肉(Beef),鱼丸(FishB

javascript装饰器模式

众所周知装饰器模式用于给对象在运行期间动态的增加某个功能,职责等.相较通过继承的方式来扩充对象的功能,装饰器显得更加灵活,首先,我们可以动态给对象选定某个装饰器,而不用hardcore继承对象来实现某个功能点.其次:继承的方式可能会导致子类繁多,仅仅为了增加某一个单一的功能点,显得有些多余了. 装饰器经典实现 首先来看看传统的decorator的实现吧!假设现有一类叫Person 的对象,该对象有个speak 方法.开始的时候Person 的对象只会说中文,现在我要让他说英文,那么可以这么做:

设计模式——代理模式与装饰器模式

代理模式 解决的问题:在直接访问对象时带来很大的开销.在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层. 代理模式就相当于Windows 里面的快捷方式,它并不实现什么功能,而只是在中间加以控制:而装饰器模式为了增强功能. Java中的典型示例:静态代理:hibernate中的session.load()方法:动态代理:SpringAOP 代码

【设计模式】之装饰器模式

为什么会有装饰模式? 装饰模式是为了解决继承强依赖性和出现大量子类不方便管理问题而出现的.   1. 概述 动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更灵活. 原理:增加一个修饰类包裹原来的类,包裹的方式一般是通过在将原来的对象作为修饰类的构造函数的参数.装饰类实现新的功能,但是,在不需要用到新功能的地方,它可以直接调用原来的类中的方法.修饰类必须和原来的类有相同的接口. 2. 模式中的角色 2.1 抽象构建(Component):定义一个抽象接口,用以给这些对象动态

Decorator Pattern(装饰器模式)Demo1

一个简单的装饰器模式例子,用来体现直接查询,缓存查询,和过滤敏感词汇 1 import java.sql.Connection; 2 import java.sql.PreparedStatement; 3 import java.sql.ResultSet; 4 import java.sql.SQLException; 5 import java.util.ArrayList; 6 import java.util.HashMap; 7 import java.util.List; 8 im