zoukankan      html  css  js  c++  java
  • 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>
        /// 使用CastleDynamicProxy 实现动态代理
        /// 方法必须是虚方法
        /// </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);
            } 
    
        }
    

      

  • 相关阅读:
    java动态代理(JDK和cglib实现对比)
    SynchronizedMap和ConcurrentHashMap 区别
    Spring五个事务隔离级别和七个事务传播行为
    Java 得到磁盘以及内存信息
    java Properties类得到当前的系统属性
    Java Runtime 详解
    java多线程设计模式
    java 得到以后的日期
    apache 配置
    centos7 安装keepalived
  • 原文地址:https://www.cnblogs.com/wxylog/p/10000228.html
Copyright © 2011-2022 走看看