上一篇中主要讲解了如何使用Spring IOC实现依赖注入的。但是操作的时候,有个很明显的问题没有解决,就是日志记录问题。如果手动添加,上百个上千个操作,每个操作都要写一遍WriteLog方法,工作量的巨大是可想而知的,更别说还有用户验证这块了。所以说,解决这种问题的方法最好是进行类的横切,OK,让我们进入正题吧。

首先,在解决方案中新建一个名称为BookStore.AOP的类库项目,然后向其中添加IAdvice并继承自IMethodInterceptor接口和IDisposable接口。

然后定义三个方法:

void Initializement();

void BeforeCall(IMethodInvocation invocation);

void AfterCall(IMethodInvocation invocation);

具体代码如下:

   1:  using System;
   2:  using AopAlliance.Intercept;
   3:   
   4:  namespace BookStore.AOP
   5:  {
   6:      public interface IAdvice : IMethodInterceptor, IDisposable
   7:      {
   8:          void Initializement();
   9:          void BeforeCall(IMethodInvocation invocation);
  10:          void AfterCall(IMethodInvocation invocation);
  11:      }
  12:  }

其中Initializement方法主要提供初始化行文;BeforeCall方法主要是在函数执行前触发;AfterCall方法主要是在函数执行后触发。

建立好这个接口之后,新建一个LogAdvice类,继承自刚刚建立的IAdvice接口,并添加如下代码:

   1:  using System;
   2:   
   3:  namespace BookStore.AOP
   4:  {
   5:      /*
   6:       请在需要消费AOP的地方添加对BookStore.AOP的引用,否则会出现错误。
   7:       */
   8:      public class LogAdvice:IAdvice
   9:      {
  10:          public LogAdvice()
  11:          {
  12:              Initializement();
  13:          }
  14:   
  15:          private log4net.ILog log;
  16:   
  17:          public void Initializement()
  18:          {
  19:              log4net.Config.XmlConfigurator.Configure();
  20:              log = log4net.LogManager.GetLogger(typeof(LogAdvice));
  21:          }
  22:   
  23:          public void BeforeCall(AopAlliance.Intercept.IMethodInvocation invocation)
  24:          {
  25:              log.Info(string.Format("调用函数开始:{0}", invocation.Method.Name));
  26:          }
  27:   
  28:          public void AfterCall(AopAlliance.Intercept.IMethodInvocation invocation)
  29:          {
  30:              log.Info(string.Format("调用函数结束:{0}", invocation.Method.Name));
  31:          }
  32:   
  33:          public object Invoke(AopAlliance.Intercept.IMethodInvocation invocation)
  34:          {
  35:              try
  36:              {
  37:                  BeforeCall(invocation);
  38:                  object resultObj = invocation.Proceed();
  39:                  AfterCall(invocation);
  40:                  return resultObj;
  41:              }
  42:              catch (Exception ex)
  43:              {
  44:                  log.Error(string.Format("调用函数错误:{0},{1},{2}", invocation.Method.Name, ex.Message, ex.StackTrace));
  45:                  return null;
  46:              }
  47:          }
  48:   
  49:          public void Dispose()
  50:          {
  51:              
  52:          }
  53:      }
  54:  }

由于这里的日志记录,我采用了Log4net来进行配置,所以不懂的同学,可以参考我之前的文章Log4Net使用方法小记来进行。

需要说明一点的是,在BeforeCall函数,AfterCall函数,Invoke函数中,我们得到的传入参数都是AopAlliance.Intercept.IMethodInvocation,通过这个参数,我们可以拦截用户当前请求的是什么函数,什么类型等等,非常方便。需要特别注意的是,在Invoke方法中,程序调用invocation.Proceed来拦截函数的执行,这也就是所谓的方法横切操作。

写到这里,我们的编码工作算是完成了,下面来开始配置AOP横切。

打开BookStore.RestService项目,双击Web.config配置文件,新添加如下的节点段落,名称分别为BookRepositoryAOP以及LogTraceAroundAdvice:

   1:  <!--Spring Config Node-->
   2:    <spring>
   3:      <context>
   4:        <resource uri="config://spring/objects"/>
   5:      </context>
   6:      <objects xmlns="http://www.springframework.net">
   7:        <!--without aop-->
   8:        <object name="BookRepository" type="BookStore.Data.BookRepository, BookStore.Data" />
   9:        
  10:        <!--with aop-->
  11:        <object name="BookRepositoryAOP" type="Spring.Aop.Framework.ProxyFactoryObject" >
  12:          <property name="Target">
  13:            <object type="BookStore.Data.BookRepository, BookStore.Data" />
  14:          </property>
  15:          <property name="InterceptorNames">
  16:            <list>
  17:              <value>LogTraceAroundAdvice</value>
  18:            </list>
  19:          </property>
  20:        </object>
  21:        <!--Advices-->
  22:        <object id="LogTraceAroundAdvice" type="BookStore.AOP.LogAdvice, BookStore.AOP"></object>
  23:      </objects>
  24:    </spring>

其中名称为BookRepositoryAOP的节点表明当前采用AOP方式进行,横切的目标是BookStore.Data.BookRepository;横切的处理是BookStore.AOP.LogAdvice。配置好后,一定不要忘记添加对BookStore.AOP项目的引用。

这之后,打开BookService类,修改构造初始化为刚刚配置的节点:

   1:   public BookService()
   2:              : base()
   3:          {
   4:              bookRepository = (IBookRepository)applicationContext["BookRepositoryAOP"];
   5:          }

然后执行,我们就可以看到拦截的日志消息了,如果执行的时候,出现错误,还能够将错误信息捕捉,是不是感觉有了AOP,腰不酸了,腿不痛了的感觉呢?

这节就到这里了,下节主要讲解用户验证这块,也是利用横切来进行。

这里允许我白话一下:接口这东西在小项目中根本用不到,但是在大项目中,是必不可少的。IOC,AOP全靠它了。并且模块与模块之间交互,利用接口来规范,大大降低了耦合度,真好啊。

TinyFrame再续篇:整合Spring AOP实现日志拦截的更多相关文章

  1. Spring AOP进行日志记录,管理

    在java开发中日志的管理有很多种.我一般会使用过滤器,或者是Spring的拦截器进行日志的处理.如果是用过滤器比较简单,只要对所有的.do提交进行拦截,然后获取action的提交路径就可以获取对每个 ...

  2. Spring AOP统一日志 全量日志

    Spring AOP 切面@Around注解的具体使用 lichuangcsdn 2019-02-19 23:21:36 63936 收藏 61分类专栏: Spring 文章标签: Spring AO ...

  3. Spring AOP 完成日志记录

    Spring AOP 完成日志记录 http://hotstrong.iteye.com/blog/1330046

  4. Spring AOP进行日志记录

    在java开发中日志的管理有很多种.我一般会使用过滤器,或者是Spring的拦截器进行日志的处理.如果是用过滤器比较简单,只要对所有的.do提交进行拦截,然后获取action的提交路径就可以获取对每个 ...

  5. TinyFrame尾篇:整合Spring AOP实现用户认证

    创建Manager用户验证表 这一篇主要讲解使用AOP对用户操作进行验证,如果通过验证,则继续执行,反之,则不能执行.其思想和上一篇完全一致. 由于需要用到用户认证,所以我们新建一个Manager实体 ...

  6. spring aop实现日志收集

    概述 使用spring aop 来实现日志的统一收集功能 详细 代码下载:http://www.demodashi.com/demo/10185.html 使用spring aop 来实现日志的统一收 ...

  7. 使用Spring AOP 实现日志管理(简单教程)

    有时候,我们在做项目时会遇到这样的需求: 给XXX.java中的所有方法加上指定格式的日志输出. 针对这种指定类.或者指定方法进行共性操作的功能,我们完全可以使用Spring AOP来实现. 本文使用 ...

  8. Spring AOP原理及拦截器

    原理 AOP(Aspect Oriented Programming),也就是面向方面编程的技术.AOP基于IoC基础,是对OOP的有益补充. AOP将应用系统分为两部分,核心业务逻辑(Core bu ...

  9. Spring AOP的日志记录

    现在的项目是Spring+MyBatis,前段时间项目经理让我干了一个活,就是给所有的controller里的所有方法加上日志记录的代码,其实没有多少,也就300来个方法,也没有抱怨什么,一边打着瞌睡 ...

随机推荐

  1. Ubuntu/Windows双系统修复引导

    Ubuntu/Windows双系统修复引导   首先说明:在Windows存在的前提下安装Ubuntu(或者Ubuntu系列)是不需要修复引导的.因为grub会自动搜索存在硬盘中的系统.   而在Ub ...

  2. WEB核心IOC篇

    ioc概念的理解:(不是技术是一种设计思想) IOC (控制反转)     IoC(Inverse of Control)的字面意思是 控制反转 ,它包括两个内容:     其一是控制 (控制对象的实 ...

  3. sql server使用中遇到的问题记录

    一.sql server 不能连接远程服务器,但可以连接本地的数据库 我目前用的是sql server 2012 sp1,用着用着突然就不能连接远程服务器上的数据库了,崩溃了一天... 修复试了,卸载 ...

  4. Javascript之旅——第十站:为什么都说闭包难理解呢?

    研究过js的朋友大多会说,理解了js的原型和闭包就可以了,然后又说这些都是js的高级内容,然后就又扯到了各种神马的作用域...然后不少 人就会被忽悠的云里雾里...下面我也试着来说说闭包,看我说的这个 ...

  5. SQL SERVER 查看数据库表的字段类型,是否允许为NULL,默认值,主键等

    )-- 表名 set @table_name='bqcform101' --============表结构 select 类别,表名or字段名,描述,字段类型,是否自增,允许为NULL,默认值 fro ...

  6. Linux的文件时间

    在windows下,一个文件有:创建时间.修改时间.访问时间.而在Linux下,一个文件也有三种时间,分别是:访问时间.修改时间.状态改动时间. 1.访问时间,读一次这个文件的内容,这个时间就会更新. ...

  7. Unity自学路线整理(参看微信公众号Unity墙外的世界的文章 )

    目前还是个新手. 发现自己有时候还是会一脸蒙...的对着电脑屏幕不知所措,为了利用好在大学零散的时间所以整理一下学习unity的路线. 计划好才能更好的利用时间. 1. 先学好C#再去看引擎,我看的是 ...

  8. MMORPG大型游戏设计与开发(客户端架构 part12 of vegine)

    在游戏中的交互过程中输入是一个必不可少的过程,比如登陆的时候需要用户输入用户名与密码,就算是单机游戏很多时候也要求用户输入一个用户名作为存档的依据.网络游戏中没有了输入,只用鼠标来交互是不切实际的,因 ...

  9. 校园导游系统(C++实现,VC6.0编译,使用EasyX图形库)

    运行效果: 说明: 由于当年还不会使用多线程,所以很多获取用户点击的地方都是使用循环实现的...CPU占用率会比较高. 代码: //校园导游系统.cpp 1 #include <graphics ...

  10. Unity3D中的预制件(Prefab)的创建和使用说明!!!

    首先我说明一下什么预制件? 在U3D里面我们叫它Prefab:我们可以这样理解:当制作好了游戏组件(场景中的任意一个gameobject),我们希望将它制作成一个组件模版,用于批量的套用工作,例如说场 ...