码迷,mamicode.com
首页 > 编程语言 > 详细

Spring.net--AOP

时间:2015-05-29 23:15:04      阅读:154      评论:0      收藏:0      [点我收藏+]

标签:aop

引言


 AOP的意思是面向方面编程,英文全称是Aspect Oriented Programming,它的作用是讲彼此先和在一起的功能分离开,简单来说就是解耦和。


原理:


我们编写应用程序时,通常包含两种代码:一种是和业务系统有关的代码,一是和业务系统关系不大的代码,例如日志、权限、异常处理、事务处理等。以前编写代码时,这两种代码基本是写在一起的,这样在程序中,到处充满着相同或类似的代码,例如日志信息的输出,每个方法都要写日志的输出,不利于程序的维护。而AOP就是使这两种代码分离的思想。使用AOP,就不用在业务逻辑中实现与业务功能关系不大的代码,从而降低了两种代码的耦合性,达到易于维护和重用的目的。


当然我觉得,现在我们使用AOP已经不仅仅满足于日志、权限、异常处理、事务处理,可以将一些经常公用的代码抽出来作为切面,这个时候,当我们那个系统用就可以调用这个切面。当然我觉得这面也可以有跟业务有关的方法,同样可以作为切面使用。


AOP的简单解释:基本上每个方法都要用日志进行记录,那么如果按照面向对象的思路来说,就是每个对象都有记录日志这样一个行为。要在每个方法里添加日志的信息,必然会产生大量的重复代码,但可以将记录日志看作是一个横切面,所有对这些方法的调用都要经过这个横切面,然后在这个横切面进行记录日志的操作,这样就达到代码重用和易于维护的目的了,这就是AOP的思想。


实现:


AOP的两种方法:


1、作为构造器参数,通过参数将对象注入到另外一个对象中。

2、我们可以将依赖对象交给外部容器负责创建。就是依赖注入,依赖注入就是指在运行期,由外部容器动态地将依赖对象注入到组件中。


我们现在只用第2种方法实现:


实现方法:通过XML文件进行依赖注入,将方法拦截,拦截的方法通过三种方式来将切面切入方法中。


实现代码:


1、MVC中建立的架构:

技术分享


2、然后IService.cs类:


<span style="font-family:SimSun;font-size:18px;">using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WebDemo
{
    public interface IService
    {
        IList FindAll();

        void Save(object entity);

        void AddString(string entity);

        void DeleteString(object entity);
    }
}</span>

CategoryService.cs类集成了IService类:


<span style="font-family:SimSun;font-size:18px;">using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using WebDemo.Models;

namespace WebDemo
{
    public class CategoryService : IService
    {
        public IList FindAll()
        {
            return new ArrayList();
        }

        public void Save(object entity)
        {
            Console.WriteLine("保存:" + entity);
        }
        public void AddString(string entity)
        {
            //Console.WriteLine("添加:" + entity);
            SchoolDbContext dbContext = new SchoolDbContext();


            UserInfo user = new UserInfo() { UName = entity, UPwd = "123" };

            MemcacheHelper.Set(entity, user, DateTime.Now.AddMinutes(20));

            dbContext.UserInfo.Add(user);
            dbContext.SaveChanges();
        }

        public void DeleteString(object entity)
        {
            //Console.WriteLine("删除:" + entity);
        }
    }
}</span>

在ProduciService.cs类,该类继承了IService:


<span style="font-family:SimSun;font-size:18px;">using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using WebDemo.Models;
using ITOO.Library.Core.Memcache;

namespace WebDemo
{
    public class ProductService : IService
    {
        public IList FindAll()
        {
            return new ArrayList();
        }

        public void Save(object entity)
        {
            Console.WriteLine("保存:" + entity);
        }

        public void AddString(string entity)
        {
            //Console.WriteLine("添加:" + entity);
            string connectionString = "Data Source=192.168.24.233;user id=sa;password=123456;persist security info=True;database=" + entity;

            SchoolWoeDbContext dbContext1 = new SchoolWoeDbContext(connectionString);

            UserInfo m2 = new UserInfo();
            UserInfo m1 = (UserInfo)ITOO.Library.Core.Memcache.MemcacheHelper.GetObject(m2, entity);

            dbContext1.UserInfo.Add(m1);
            dbContext1.SaveChanges();
        }

        public void DeleteString(object entity)
        {
            //Console.WriteLine("删除:" + entity);
        }
    }
}</span>

3、Advice中的三个类的代码为:


AfterAdvice类:

<span style="font-family:SimSun;font-size:18px;">using AopAlliance.Intercept;
using Spring.Aop;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WebDemo
{
    public class AfterAdvice : IAfterReturningAdvice
    {

        public void AfterReturning(object returnValue, System.Reflection.MethodInfo method, object[] args, object target)
        {
            Console.WriteLine("开始:  " + method.Name);
        }

    }
}</span>

AroundAdvice类:


<span style="font-family:SimSun;font-size:18px;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using AopAlliance.Intercept;

namespace WebDemo
{
    public class AroundAdvice : IMethodInterceptor
    {
        public object Invoke(IMethodInvocation invocation)
        {

            Console.WriteLine("开始:  " + invocation.TargetType.Name + "." + invocation.Method.Name);
            object result = invocation.Proceed();
            Console.WriteLine("结束:  " + invocation.TargetType.Name + "." + invocation.Method.Name);
            return result;
        }
    }
}</span>


BeforeAdvice类:


<span style="font-family:SimSun;font-size:18px;">using AopAlliance.Intercept;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WebDemo
{
    public class BeforeAdvice : Spring.Aop.IMethodBeforeAdvice,IMethodInterceptor
    {
        public object Invoke(IMethodInvocation invocation)
        {
            object result = invocation.Proceed();
            Console.WriteLine("前置开始:  " + invocation.TargetType.Name + "." + invocation.Method.Name);

            Console.WriteLine("前置结束:  " + invocation.TargetType.Name + "." + invocation.Method.Name);

            return result;

        }

        public void Before(System.Reflection.MethodInfo method, object[] args, object target)
        {
            Console.WriteLine("前置结束:  " + method.Name );
        }
    }
}
</span>


3、配置XML节点:


在<configSections>节点中添加节点:


<span style="font-family:SimSun;font-size:18px;">    <sectionGroup name="spring">
      <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" />
      <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
    </sectionGroup></span>

在<configuration>中添加:


<span style="font-family:SimSun;font-size:18px;">  <spring>

    <context>
      <resource uri="config://spring/objects" />
    </context>

    <objects xmlns="http://www.springframework.net" xmlns:aop="http://www.springframework.net/aop">
      <description>配置实现AOP</description>

      <!--必须要写的,不让不能拦截,对象名切入点:ObjectNameAutoProoxyCreateor-->
      <object id="ProxyCreator" type="Spring.Aop.Framework.AutoProxy.ObjectNameAutoProxyCreator, Spring.Aop">
        <property name="ObjectNames">
          <list>
            <value>*Service</value>
          </list>
        </property>
        <property name="InterceptorNames">
          <list>
            <!--<value>beforeAdvisor</value>-->
            <!--<value>afterAdvisor</value>-->
            <value>AroundAdvisor</value>
          </list>
        </property>
      </object>

      <!--加载  外部方法-->
      <!--<object id="afterAdvice" type="Common.AfterAdvice, Common"/>-->
      <object id="AroundAdvice" type="WebDemo.AroundAdvice, WebDemo"/>

      <!--<object id="beforeAdvice" type="Common.BeforeAdvice, Common"/>-->
      <!--配置 要拦截的类-->
      <object id="categoryService" type="WebDemo.ProductService, WebDemo"/>
      <object id="productService" type="WebDemo.ProductService, WebDemo"/>
      <!--必须要写的,不让不能拦截,对象名切入点:ObjectNameAutoProoxyCreateor-->



      <!--拦截使用的方法-->
      <!--<object id="beforeAdvisor" type="Spring.Aop.Support.NameMatchMethodPointcutAdvisor, Spring.Aop">-->
      <!--<object id="afterAdvisor" type="Spring.Aop.Support.NameMatchMethodPointcutAdvisor, Spring.Aop">
        <property name="Advice" ref="afterAdvice"/>-->
      <object id="AroundAdvisor" type="Spring.Aop.Support.NameMatchMethodPointcutAdvisor, Spring.Aop">
        <property name="Advice" ref="AroundAdvice"/>
        <property name="MappedNames">
          <list>
            <!--方法名的匹配-->
            <!--<value>*</value>-->
            <!--<value>Find*</value>-->
            <!--<value>Save*</value>
            <value>del*</value>
            <value>query*</value>-->
            <value>Add*</value>
            <value>Del*</value>
          </list>
        </property>
      </object>
      <!--<object id="beforeAdvisor" type="Spring.Aop.Support.NameMatchMethodPointcutAdvisor, Spring.Aop">
        <property name="Advice" ref="beforeAdvice"/>
        <property name="MappedNames">
          <list>
            -->
      <!--方法名成的匹配-->
      <!--
            <value>Find*</value>
            <value>Save*</value>
          </list>
        </property>
      </object>-->



    </objects>

  </spring>
</span>


上面的配置就是我将所有的categoryService和productService中的Add和Del开头的方法全部拦截,之后通过AroundAdvice方法进行切入。这个时候,其实我们可以通过Memcached来讲所有的变量进行传递,这样就可以实现方法与方法之间的参数传递了。


4、测试方法:


在AOPController中:


<span style="font-family:SimSun;font-size:18px;">using Spring.Context;
using Spring.Context.Support;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using WebDemo.Models;

namespace WebDemo.Controllers
{
    public class AOPController : Controller
    {
        //
        // GET: /AOP/

        public ActionResult Index()
        {
            return View();
        }
        public String Search(string item)
        {
            IApplicationContext ctx = ContextRegistry.GetContext();       
            IDictionary speakerDictionary = ctx.GetObjectsOfType(typeof(IService));//把所有的实现IService接口的类都加载出来
            foreach (DictionaryEntry entry in speakerDictionary)
            {
                string name = (string)entry.Key;            //获取类的方法名称
                IService service = (IService)entry.Value;     //获取该类
                Console.WriteLine(name + " 拦截: ");         

                service.AddString("qmx");                     //需要通过AOP拦截的方法

            }


            return "123";
        }
    }

}</span>

在Index.cshtml文件中:


<span style="font-family:SimSun;font-size:18px;">@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>
<input type="button" id="button" value="拦截Add" onclick="add()" />
<script type="text/javascript">
    function add() {
        var item = "qmx";
        $.get("/AOP/Search/", { item: item }, function (string) {
            alert("添加成功!");
        });
    }
</script></span>

这样一个简单的AOP就做出来了。


总结:


AOP是一种思想,不是一种技术,这种思想通过容器的思想,以依赖注入的形式,将业务与业务之间进行了解耦,在很大程度上减少了我们的代码量。AOP的实现还有很多,但是大体上的本质是不会变的,变的可能就实现AOP的方式了。







Spring.net--AOP

标签:aop

原文地址:http://blog.csdn.net/qiumuxia0921/article/details/46228787

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!