AOP面向切面编程(Aspect Oriented Programming的缩写),是OOP(面向对象编程)的一种延续形式。是通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术,它从一个不同于OOP的角度来看待程序的结构:OOP将应用程序分解为一系列表现为继承关系的对象;AOP 则把程序分解为一系列方面(aspects)或者关注点(concerns)。AOP将诸如事务管理等本来横向分布在多个对象中的关注点进行了模块化处理(这些关注点也常称为横切(crosscutting)关注点)。在Spring.NET中提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。

  下面我举个例子来说明这一切:

  场景:业务类CompanyManager在调用Save方法的时候需要调用SecurityManager类判断权限是否足够(图1)。

图1

  准备条件:

    public class CompanyDao
    {
        public void Save()
        {
            Console.WriteLine("保存数据");
        }
    }
    public interface ICompanyManager
    {
        string UserName { get; set; }

        void Save();
    }
    public interface ISecurityManager
    {
        bool IsPass(string userName);
    }
SecurityManager
    public class SecurityManager : ISecurityManager
    {
        /**//// <summary>
        /// 判断权限
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        public bool IsPass(string userName)
        {
            return userName == "admin";
        }
    }

  第一种实现方式,我们通常会这样做:直接在CompanyManager类中调用ISecurityManager接口的IsPass方法判断权限。

SimpleCompanyManager
public class SimpleCompanyManager : ICompanyManager
    {
        可通过外部注入的属性#region 可通过外部注入的属性

        public string UserName { get; set; }

        public CompanyDao Dao { get; set; }

        #endregion

        public void Save()
        {
            //判断权限
            ISecurityManager security = new SecurityManager();
            if (security.IsPass(UserName))
            {
                //执行业务方法
                //.
                //调用DAO层方法
                Dao.Save();
            }
            else
            {
                //执行其它业务方法
                Console.WriteLine("您没有该权限");
            }
        }
    }

  这样CompanyManager类与ISecurityManager或SecurityManager会发生业务性耦合。聪明的朋友会发现在GOF(设计模式)中有一种模式(代理模式)可以解除这种耦合。

  第二种实现方式,代理模式(Proxy Pattern):什么是代理模式?是给某一个对象提供一个代理对象,并由代理对象控制对源对象的引用。代理就是一个人或一个机构代表另一个人或者一个机构采取行动。某些情况下,客户不想或者不能够直接引用一个对象,代理对象可以在客户和目标对象直接起到中介的作用。客户端分辨不出代理主题对象与真实主题对象。代理模式可以并不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,这时候代理对象不能够创建被代理对象,被代理对象必须有系统的其他角色代为创建并传入(图2)。
图2

CompanyManager
    public class CompanyManager : ICompanyManager
    {
        可通过外部注入的属性#region 可通过外部注入的属性

        public string UserName { get; set; }

        public CompanyDao Dao { get; set; }

        #endregion

        public void Save()
        {
            //执行业务方法
            //.
            //调用DAO层方法
            Dao.Save();
        }
    }
CompanyProxyManager
    public class CompanyProxyManager : ICompanyManager
    {
        public string UserName { get; set; }

        private ICompanyManager target = new CompanyManager();

        public void Save()
        {
            //判断权限
            ISecurityManager security = new SecurityManager();
            if (security.IsPass(UserName))
            {
                //调用目标对象Save方法
                target.Save();
            }
            else
            {
                Console.WriteLine("您没有该权限");
            }
        }
    }

  这样,CompanyManager类就不必与判断权限的类SecurityManager耦合,但是这种方式实现起来比较麻烦。

  第三种实现方式,Spring.NET提供的AOP:AopAlliance.Intercept.IMethodInterceptor接口和ProxyFactory类的组合。

AroundAdvice
    public class AroundAdvice : IMethodInterceptor
    {
        //权限系统类(可外部注入)
        private ISecurityManager manager = new Service.SecurityManager();

        public object Invoke(IMethodInvocation invocation)
        {
            //拦截Save方法
            if (invocation.Method.Name == "Save")
            {
                ICompanyManager target = (ICompanyManager)invocation.Target;

                return manager.IsPass(target.UserName) ? invocation.Proceed() : null;
            }
            else
            {
                return invocation.Proceed();
            }
        }
    }
Program
    class Program
    {
        static void Main(string[] args)
        {
            ICompanyManager target = new CompanyManager() { Dao = new CompanyDao(), UserName = "admin" };
            
            ProxyFactory factory = new ProxyFactory(target);
            factory.AddAdvice(new AroundAdvice());

            ICompanyManager manager = (ICompanyManager)factory.GetProxy();
            manager.Save();

            Console.ReadLine();
        }
    }

  输出:保存数据
  

  Spring.NET利用System.Reflection.Emit命名空间下的类在运行时动态创建IL代码来生成AOP代理。这使得代理(的创建)非常高效,并且不受任何继承层次的限制。

  参考:Spring.NET中文手册

  李会军博客代理模式http://www.cnblogs.com/terrylee/archive/2006/05/18/403382.html

  代码下载

  返回目录

Spring.NET学习笔记12——面向切面编程(基础篇) Level 300相关推荐

  1. Spring.NET学习笔记10——方法的注入(基础篇) Level 200

    多数用户都会将容器中的大部分对象布署为singleton模式.当一个singleton对象需要和另一个singleton对象协作,或者一个非singleton对象需要和另一个非singleson对象协 ...

  2. Spring.NET学习笔记13——AOP的概念(基础篇) Level 200

    上篇我们简单的了解了AOP的应用场景,知道AOP编程的重要性.这篇我们先看一段代码,来开始今天的学习. 回顾与上篇类似的代码:SecurityService类的IsPass判断用户名为"ad ...

  3. Spring.NET学习笔记15——AOP的配置(基础篇) Level 200

    上篇我学习了Spring.NET的四种通知类型,AOP的实现方案比较复杂,是通过代码实现的.而Spring.NET框架给我们提供了配置的方式来实现AOP的功能.到目前为止,我们已经讨论过使用Proxy ...

  4. Spring.NET学习笔记11——自定义对象行为(基础篇) Level 200

    Spring.NET通过几个专门的接口来控制容器中对象的行为.说到对象的行为无非就要提到对象的生命周期控制.类似在WinForm开发,Form生命周期中,Load方法为Form的载入方法和Dispos ...

  5. python aop编程_学习笔记: AOP面向切面编程和C#多种实现

    AOP:面向切面编程   编程思想 OOP:一切皆对象,对象交互组成功能,功能叠加组成模块,模块叠加组成系统 类--砖头     系统--房子 类--细胞     系统--人 面向对象是非常适合做大型 ...

  6. MATLAB学习笔记3:MATLAB编程基础(前半)

    阅读前请注意: 1. 该学习笔记是华中师范大学HelloWorld程序设计协会2021年寒假MATLAB培训的学习记录,是基于培训课堂内容的总结归纳.拓展阅读.博客内容由 @K2SO4钾 撰写.编辑, ...

  7. Python学习之旅(核心编程基础篇003运算符)

    Python学习之旅 Python核心编程基础篇2020.12.18 一.算数运算符 二.比较运算符 三.赋值运算符 四.逻辑运算符 五.成员运算符 六.身份运算符 七.三目运算符 八.运算符优先级 ...

  8. Spring学习之AOP(面向切面编程)

    动态代理 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关 ...

  9. Spring in Action 入门之面向切面编程AOP

    注明:这篇文章一是当成学习笔记,二是给大家提供另一个快速理解学习Spring的参考.欢迎留言讨论,持续更新中~ (该部分是Spring的面向切面编程AOP) 第四章 通知Bean 在软件编程中,散布于 ...

最新文章

  1. 线程同步——内核对象实现线程同步——等待函数
  2. 金山毒霸2007终身升级版V8.0正式上线(2006.12.30最新版)
  3. 给FlvDownloader加了一个视频预览的功能
  4. 东软软件动态生成对数据表更新操作的方法
  5. cv2读取np的矩阵图片,numpy数组clip和astype,查看数据类型array.dtype
  6. 14-2 正则表达式
  7. [C# 线程处理系列]专题四:线程同步
  8. 动态系统建模与仿真 基本知识笔记(源自DR_CAN)
  9. php varbinary,MySQL 数据类型binary和varbinary的简单示例
  10. 软工文档-项目开发计划
  11. mysql 身份证号码判断
  12. 蓝桥杯算法训练VIP-调和数列问题
  13. 解决IOS微信SDK初始化失败
  14. qt清空qtablew_qt项目:员工信息管理系统
  15. Codeforces Round #116 C.Letter
  16. deepnode软件下载地址_安卓苹果软件下载地址恢复
  17. Android——自建CA证书,实现https请求
  18. 什么是安全隔离R型变压器?
  19. 手机便签内容修改后可以恢复吗?
  20. 废旧计算机cpu diy,手把手教你从废旧CPU提取金银

热门文章

  1. linux gcc 简单使用记录01
  2. c++实现任意类型数组类的封装
  3. 韦东山嵌入式第一期14课第004节_und异常模示程序示例_P笔记
  4. 【Leetcode | 12】342. 4的幂
  5. 三面美团Java岗,java多线程匿名内部类
  6. JavaScript数组(2)---遍历/迭代方法 8种
  7. php+nginx导入太大文件报http error错误的原因
  8. 堆溢出的DWORD Shoot核心原理-口语化
  9. Linux环境下使用rpm包安装GitLab
  10. Oracle RAC