AOP拦截记录日志

2023-10-27

首先对于AOP切面编程,我也是刚学习,了解不深,这边先引用老张的博客,方便大家学习。

 首先想一想,如果有这么一个需求,要记录整个项目的接口和调用情况,当然如果只是控制器的话,还是挺简单的,直接用一个过滤器或者一个中间件,还记得咱们开发Swagger拦截权限验证的中间件么,那个就很方便的把用户调用接口的名称记录下来,当然也可以写成一个切面,但是如果想看下与Service或者Repository层的调用情况呢,好像目前咱们只能在Service层或者Repository层去写日志记录了,那样的话,不仅工程大(当然你可以用工厂模式),而且耦合性瞬间就高了呀,想象一下,如果日志要去掉,关闭,修改,需要改多少地方!您说是不是,好不容易前边的工作把层级的耦合性降低了。别慌,这个时候就用到了AOP和Autofac的Castle结合的完美解决方案了。【 .NET Core 3.0 】框架之十 || AOP 切面思想 (qq.com)

 正文开始

一开始我记录日志是Nlog,采用autofac注入。然后在服务层仓储层或者你想记录的地方去注入然后记录日志,NLog的使用教程我也有记录,可以翻看一下:

但是这样每一个方法每一个类都要进行注入。上边 的引用所说的 耦合性增加,因为我是通过Autofac程序集依赖注入的,耦合性倒还好。最大的问题可能在于,每一个方法我都要单独的去写日志记录。就很麻烦,因此采用这种AOP拦截记录日志,方便很多。

专业术语很多,我也不是很理解,感觉挺牛的。不过单独针对于记录日志这方面,还是挺简单的。

老张的项目结构式有一个扩展的类库,专门来搞这些。我添加到了Common公共类库里,操作完之后,感觉对于我自己的项目直接写在API底下应该更方便,因为一开始使用autofac是安装到仓储层了。这样一层层的调用 API>IService>IRepository 可以少安装Get包和少一些引用。不过也没什么关系了,Common本身我打算的就是任何地方都可以去引用(不过因为没有Nlog包所有多安装了一个,以后精通了再修改完善吧)。

1

  1. 创建一个类,继承[IInterceptor]  我这里是记录日志的,叫LogAOP

  2. 继承之后,实现这个类的唯一方法Intercept

  3. 记录日志的过程在方法Intercept里实现,我会配合我自己的代码来写对应的注释。

public class LogAOP : IInterceptor
    {
        protected readonly ILogger<LogAOP> Nlog;

        /// <summary>
        /// 采用Nlog记录日志,同样使用构造函数注入Nlog
        /// </summary>
        /// <param name="logger"></param>
        public LogAOP(ILogger<LogAOP> logger)
        {
            Nlog = logger;
        }

        /// <summary>
        /// 实现继承IInterceptor的方法
        /// </summary>
        /// <param name="invocation"></param>
        public void Intercept(IInvocation invocation)
        {
            //记录日志的String,在请求接口的时候会先进行拦截,可以获取到方法的名称,方法在哪个位置,所带参数等
            var dataIntercept = "\n\t" +
                 $"【当前执行方法:{invocation.Method.Name}】\n\t" +
                 $"【携带的参数有:{string.Join(",", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray())}】\n\t" +
                 $"【当前执行方法的位置:{invocation.InvocationTarget}】\n\t";

            try
            {
                //这个Proceed是执行这个方法,不写的话就204,不会处理该请求
                invocation.Proceed();
                //如果Proceed成功执行,则返回到请求的结果
                dataIntercept += ($"【执行完成结果:】{JsonSerializer.Serialize(invocation.ReturnValue)}");
            }
            catch (Exception e)
            {
                //如果Proceed里面异常了,就会在此处获取到异常信息。
                dataIntercept += ($"【方法异常:】{e.Message + e.InnerException}");
            }
            //为了在日志里划分区域范围,容易查看
            dataIntercept += ("\n\n=======================================================================");
            //这个地方目前我不知道怎么解释,但是记录日志要写在里面
            Parallel.For(0, 1, e =>
            {
                Nlog.LogInformation(dataIntercept);
            });
        }
    }

然后就是将这个类注入到程序内。红框里的是注入aop拦截新加 的,其余的就是注入仓储和服务层的,这种比较偏底层,目前我无法解释太清楚,如果有大佬看到了可以解释一二。我的理解呢就是

2

  1. builder.RegisterType<LogAOP>();//将拦截器注册,但此时还没有确定注入到哪个地方……

  2. EnableInterfaceInterceptors:添加一个拦截,表示给你的程序哪个位置添加拦截,比如我要添加我的Service和Repository层

  3. InterceptedBy() :将XX拦截功能注册到服务,这个就是要将第一步你注入的拦截器添加到指定的位置

630245d3294b06ecb8eeed6c3d63c885.png

 看看我的效果:

8940690e2a52c4f9cb6db17b5b32198f.png

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AOP拦截记录日志 的相关文章

  • 静态只读字符串数组

    我在我的 Web 应用程序中使用静态只读字符串数组 基本上数组有错误代码 我将所有类似的错误代码保存在一个数组中并检查该数组 而不是检查不同常量字符串中的每个错误代码 like public static readonly string m
  • CLR 2.0 与 4.0 性能比较?

    如果在 CLR 4 0 下运行 为 CLR 2 0 编译的 NET 程序会运行得更快吗 应用程序配置
  • 代码 GetAsyncKeyState(VK_SHIFT) & 0x8000 中的这些数字是什么?它们是必不可少的吗?

    我试图在按下按键的简单动作中找到这些数字及其含义的任何逻辑解释 GetAsyncKeyState VK SHIFT 0x8000 可以使用哪些其他值来代替0x8000它们与按键有什么关系 GetAsyncKeyState 根据文档返回 如果
  • 从客户端访问 DomainService 中的自定义对象

    我正在使用域服务从 Silverlight 客户端的数据库中获取数据 在DomainService1 cs中 我添加了以下内容 EnableClientAccess public class Product public int produ
  • unordered_map 中字符串的 C++ 哈希函数

    看起来 C 标准库中没有字符串的哈希函数 这是真的 在任何 c 编译器上使用字符串作为 unordered map 中的键的工作示例是什么 C STL提供模板专业化 http en cppreference com w cpp string
  • 使用 LINQ to SQL 时避免连接超时的最佳实践

    我需要知道在 net 应用程序中使用 LINQ to SQL 时避免连接超时的最佳实践 特别是在返回时IQueryable
  • 类型约束

    我有以下类层次结构 class Header IEnumerable
  • 启动时的 Excel 加载项

    我正在使用 Visual C 创建 Microsoft Excel 的加载项 当我第一次创建解决方案时 它包含一个名为 ThisAddIn Startup 的函数 我在这个函数中添加了以下代码 private void ThisAddIn
  • 识别 Visual Studio 中的重载运算符 (c++)

    有没有办法使用 Visual Studio 快速直观地识别 C 中的重载运算符 在我看来 C 中的一大问题是不知道您正在使用的运算符是否已重载 Visual Studio 或某些第三方工具中是否有某些功能可以自动突出显示重载运算符或对重载运
  • 如何在 Qt 应用程序中通过终端命令运行分离的应用程序?

    我想使用命令 cd opencv opencv 3 0 0 alpha samples cpp cpp example facedetect lena jpg 在 Qt 应用程序中按钮的 clicked 方法上运行 OpenCV 示例代码
  • 在视口中查找 WPF 控件

    Updated 这可能是一个简单或复杂的问题 但在 wpf 中 我有一个列表框 我用一个填充数据模板从列表中 有没有办法找出特定的数据模板项位于视口中 即我已滚动到其位置并且可以查看 目前我连接到了 listbox ScrollChange
  • 在mysql连接字符串中添加应用程序名称/程序名称[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我正在寻找一种解决方案 在连接字符串中添加应用程序名称或程序名称 以便它在 MySQL Workbench 中的 客户端连接 下可见 SQL
  • C++ int 前面加 0 会改变整个值

    我有一个非常奇怪的问题 如果我像这样声明一个 int int time 0110 然后将其显示到控制台返回的值为72 但是当我删除前面的 0 时int time 110 然后控制台显示110正如预期的那样 我想知道两件事 首先 为什么它在
  • 等待 IAsyncResult 函数直至完成

    我需要创建等待 IAsyncResult 方法完成的机制 我怎样才能做到这一点 IAsyncResult result contactGroupServices BeginDeleteContact contactToRemove Uri
  • 检测到严重错误 c0000374 - C++ dll 将已分配内存的指针返回到 C#

    我有一个 c dll 它为我的主 c 应用程序提供一些功能 在这里 我尝试读取一个文件 将其加载到内存 然后返回一些信息 例如加载数据的指针和内存块的计数到 c Dll 成功将文件读取到内存 但在返回主应用程序时 程序由于堆损坏而崩溃 检测
  • 使 Guid 属性成为线程安全的

    我的一个类有一个 Guid 类型的属性 该属性可以由多个线程同时读写 我的印象是对 Guid 的读取和写入不是原子的 因此我应该锁定它们 我选择这样做 public Guid TestKey get lock testKeyLock ret
  • 将数组作为参数传递

    如果我们修改作为方法内参数传递的数组的内容 则修改是在参数的副本而不是原始参数上完成的 因此结果不可见 当我们调用具有引用类型参数的方法时 会发生什么过程 这是我想问的代码示例 using System namespace Value Re
  • GCC 的“-Wl,option”和“-Xlinker option”语法之间有区别吗?

    我一直在查看一些配置文件 并且看到它们都被使用 尽管在不同的体系结构上 如果您在 Linux 机器上使用 GCC 将选项传递给链接器的两种语法之间有区别吗 据我所知 阅读 GCC 手册时 他们的解释几乎相同 From man gcc Xli
  • 为boost python编译的.so找不到模块

    我正在尝试将 C 代码包装到 python 中 只需一个类即可导出两个函数 我编译为map so 当我尝试时import map得到像噪音一样的错误 Traceback most recent call last File
  • 不区分大小写的字符串比较 C++ [重复]

    这个问题在这里已经有答案了 我知道有一些方法可以进行忽略大小写的比较 其中涉及遍历字符串或一个good one https stackoverflow com questions 11635 case insensitive string

随机推荐