Unity容器实现AOP面向切面编程

为什么要有AOP

  需求总是变化的,比如经常会对一些方法后期增加日志、异常处理、权限、缓存、事务的处理,遇到这种情况我们往往只能修改类。

  为了应对变化,我们常常使用设计模式解决,但是也有其局限性:设计模式这能替换整个对象,但是没办法把一个类动态改变。所以我们需要引入AOP的编程思想,因为它允许开发者动态的修改静态的OO模型,构造出一个不断增长,不断变化的需求。

  AOP是一种编程思想,是对OOP面向对象编程思想的补充。

  使用AOP编程可以方便我们聚焦一些核心业务逻辑,比如权限、异常、日志、缓存、事务这种通用功能可以封装起来,通过AOP添加到指定的方法,简化程序设计。

如何使用AOP

1、添加引用

2、配置文件

在configuration节点下添加(注意看注释)

 <configSections>   <!--这里添加一个unity扩展-->
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration" />
  </configSections>
  <unity>
    <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration" />
    <containers>
      <!--这里最好起一个名字 方便代码查找-->
      <container name="oneBehaviorTestContainer">
        <extension type="Interception" />
        <!--设置接口的实现类-->
        <register type="IServers.IUser,IServers" mapTo="Providers.UserProvider,Providers">
          <!--InterfaceInterceptor:继承接口的方法都会被拦截。
              TransparentProxyInterceptor:继承类使用的方法都会被拦截。
              VirtualMethodInterceptor:继承的方法必须是虚方法且必须是公开的方法才会被拦截。-->
          <interceptor type="InterfaceInterceptor"/>
          <!--配置文件的注册顺序是调用顺序,然后才是业务方法,但是扩展逻辑也可以在业务方法之后-->
          <!--应该把捕捉异常的拦截器放到第一位,这样还可以捕捉其他拦截器内的异常-->
          <interceptionBehavior type="AOPExe.Interceptions.ExceptionBehavior, AOPExe"/>
          <!--应该把性能计算的拦截器放到第二位,这样还可以捕捉其他拦截器内的异常-->
          <interceptionBehavior type="AOPExe.Interceptions.MonitorBehavior, AOPExe"/>
          <!--参数检查-->
          <interceptionBehavior type="AOPExe.Interceptions.ParameterCheckBehavior, AOPExe"/>
          <!--缓存-->
          <interceptionBehavior type="AOPExe.Interceptions.CachingBehavior, AOPExe"/>
        </register>
      </container>
    </containers>
  </unity>

3、程序调用

3.1程序调用

                //声明一个Unity容器
                var container = new UnityContainer();
                //获取到Unity部分
                UnityConfigurationSection unitySection = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
                //将扩展部分注册到容器
                unitySection.Configure(container, "oneBehaviorTestContainer");
                //获取接口实例
                var userService = container.Resolve<IUser>();
                //调用接口方法(该方法被添加了拦截器)
                var user = userService.GetUser(100);
                if (user!=null)
                {
                    Console.WriteLine(user.Name);
                }

3.2 拦截器

拦截器的类要实现:IInterceptionBehavior接口

    /// <summary>
    /// 缓存(用于方法前)
    /// </summary>
    public class CachingBehavior : IInterceptionBehavior
    {
        public bool WillExecute => true;

        public IEnumerable<Type> GetRequiredInterfaces()
        {
            return Type.EmptyTypes;
        }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
        {
            return input.CreateMethodReturn(new UserModel() { Id = 1, Name = "缓存姓名" });
        }
    }  
/// <summary> /// 异常处理 /// </summary>public class ExceptionBehavior : IInterceptionBehavior
    {
        public bool WillExecute => true;

        public IEnumerable<Type> GetRequiredInterfaces()
        {
            return Type.EmptyTypes;
        }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
        {
            IMethodReturn methodReturn = getNext()(input, getNext);
            if (methodReturn.Exception != null)
            {
                //处理异常
                Console.WriteLine("ExceptionBehavior捕捉到异常:" + methodReturn.Exception.Message);
                //隐藏异常
                methodReturn.Exception = null;
            }
            else
            {
                Console.WriteLine("ExceptionBehavior没有捕捉到异常。");
            }
            return methodReturn;
        }
    }
/// <summary>
    /// 性能检测
    /// </summary>
    public class MonitorBehavior : IInterceptionBehavior
    {
        public bool WillExecute => true;

        public IEnumerable<Type> GetRequiredInterfaces()
        {
            return Type.EmptyTypes;
        }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            var returnMethod = getNext()(input, getNext);
            sw.Stop();
            Console.WriteLine("MonitorBehavior 本次方法共耗时:" + sw.ElapsedMilliseconds);
            return returnMethod;
        }
    }
/// <summary>
    /// 参数检查
    /// </summary>
    public class ParameterCheckBehavior : IInterceptionBehavior
    {
        public bool WillExecute => true;

        public IEnumerable<Type> GetRequiredInterfaces()
        {
            return Type.EmptyTypes;
        }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
        {
            Console.WriteLine("ParameterCheckBehavior,打印所有传入参数:");
            foreach (var ipt in input.Inputs)
            {
                Console.WriteLine(ipt);
            }
            int id = (int)input.Inputs[0];
            if (id > 100)
            {
                //这种写法不对
                //new Exception("Id不能超过100");
                return input.CreateExceptionMethodReturn(new Exception("Id不能超过100"));
            }
            else
            {
                Console.WriteLine("参数检查通过");
            }
            return getNext()(input, getNext);
        }
    }

3.3业务方法

 public interface IUser
    {
        UserModel GetUser(int Id);
    }
 public UserModel GetUser(int Id)
        {
            Console.WriteLine("数据库中读取UserModel,可能时间会比较长一点点(对比缓存)");
            //throw new Exception("业务方法中抛出异常");//这里抛出的异常,也可以捕获到
            Thread.Sleep(10000);
            return new UserModel()
            {
                Id = Id
                ,
                Name = "张三"
            };
        }

4、如果不想对接口内的所有方法都添加拦截该怎么办?

我能想到的办法是为接口方法添加特性,然后再拦截器内判断该方法是否含有该特性。小伙伴们有啥想法欢迎留言。

原文地址:https://www.cnblogs.com/chenxizhaolu/p/12362548.html

时间: 2024-10-05 04:56:17

Unity容器实现AOP面向切面编程的相关文章

Autofac的AOP面向切面编程研究

*:first-child { margin-top: 0 !important; } .markdown-body>*:last-child { margin-bottom: 0 !important; } .markdown-body a:not([href]) { color: inherit; text-decoration: none; } .markdown-body .anchor { float: left; padding-right: 4px; margin-left: -2

浅谈Spring AOP 面向切面编程 最通俗易懂的画图理解AOP、AOP通知执行顺序~

简介 我们都知道,Spring 框架作为后端主流框架之一,最有特点的三部分就是IOC控制反转.依赖注入.以及AOP切面.当然AOP作为一个Spring 的重要组成模块,当然IOC是不依赖于Spring框架的,这就说明你有权选择是否要用AOP来完成一些业务. AOP面向切面编程,通过另一种思考的方式,来弥补面向对象编程OOP当中的不足,OOP当中最重要的单元是类,所以万物皆对象,万物皆是 对象类.而在AOP的模块单元中,最基础的单元是切面,切面对切点进行模块化的管理. 最后再提一句:Spring当

Javascript aop(面向切面编程)之around(环绕)

Aop又叫面向切面编程,其中“通知”是切面的具体实现,分为before(前置通知).after(后置通知).around(环绕通知),用过spring的同学肯定对它非常熟悉,而在js中,AOP是一个被严重忽视的技术点.但是利用aop可以有效的改善js代码逻辑,比如前端框架dojo和yui3中AOP则被提升至自定义事件的一种内在机制,在源码中随处可见.得益于这种抽象使得dojo的自定义事件异常强大和灵活.dojo中aop的实现在dojo/aspect模块中,主要有三个方法:before.after

sprint.net(2) AOP面向切面编程,spring.net的环绕通知;Spring.net的AOP通知的四种类型

AOP 有点类似于我们MVC里面的Filter过滤器,例如在MVC里面,如果给一个Action上打一个标签,就可以在这个Action执行之前或者之后,额外的执行一个方法,这个就相当于是面向切面编程. 无侵入式的. (也就是在不改变原来的代码的情况下,来跳转到一个其他的方法,执行完毕后回到主方法..),但是spring.net的AOP更牛叉,只需要在xml里面配置,就可以了,不需要在方法上面打特性的标签,也不需要继承什么类(例如MVC的过滤器是继承了ActionFilterAttribute) 主

AOP:面向切面编程

AOP:面向切面编程(Aspect-Oriented Programming)      AOP可以说是对OOP的补充和完善.OOP引入封装.继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合.当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力.也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系.例如日志功能.日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系.在OOP设计中,它导致了大量代码的重复,而不利于各个模块的

深入探索spring技术内幕(七): 配置Spring AOP面向切面编程

一. AOP一些概念 Aspect( 切面 ): 指横切性关注点的抽象即为切面, 它与类相似, 只是两者的关注点不一样, 类是对物体特征的抽象, 而切面横切性关注点的抽象. joinpoint( 连接点 ): 指那些被拦截到的点. 在spring中, 这些点指的是方法, 因为spring只支持方法类型的连接点, 实际上joinpoint还可以是field或类构造器) Pointcut( 切入点 ): 指我们要对那些joinpoint进行拦截的定义. Advice( 通知 ): 指拦截到joinp

spring入门-AOP 面向切面编程

AOP 面向切面编程 在日常开发中最后将业务逻辑定义在一个专门的service包下,而实现定义在service包下的impl包中, 服务接口以IXXXService形式,而服务实现就是XXXService,这就是规约设计 步骤: 1.E:\Users\WorkSpaces\KmwalletApp\spring\aop\test\HelloWorldService.java 继承(implements)xx接口 2.E:\Users\WorkSpaces\KmwalletApp\spring\ao

Aspects– iOS的AOP面向切面编程的库

简介 一个简洁高效的用于使iOS支持AOP面向切面编程的库.它可以帮助你在不改变一个类或类实例的代码的前提下,有效更改类的行为.比iOS传统的 AOP方法,更加简单高效.支持在方法执行的前/后或替代原方法执行.曾经是 PSPDFKit 的一部分,PSPDFKit,在Dropbox和Evernote中都有应用,现在单独单独开源出来给大家使用. 项目主页: Aspects 最新实例:点击下载 注: AOP是一种完全不同于OOP的设计模式.更多信息,可以参考这里: AOP 百度百科 快速入门 环境要求

java aop面向切面编程

最近一直在学java的spring boot,一直没有弄明白aop面向切面编程是什么意思.看到一篇文章写得很清楚,终于弄明白了,原来跟python的装饰器一样的效果.http://www.cnblogs.com/yanbincn/archive/2012/06/01/2530377.html Aspect Oriented Programming  面向切面编程.解耦是程序员编码开发过程中一直追求的.AOP也是为了解耦所诞生. 具体思想是:定义一个切面,在切面的纵向定义处理方法,处理完成之后,回