首页 > 其他分享 >aop 阶段性概况

aop 阶段性概况

时间:2024-04-16 11:13:32浏览次数:14  
标签:阶段性 自定义 void public 概况 aop class 预处理

前言

对aop进行一个阶段性的总结。

正文

首先什么是aop呢?

那么首先看aop的解决什么样的问题。

public class Program
{
    public static void Main(string[] args)
    {
        
    }

    public void ChangePosition1()
    {
        // your operation
        SavePosition();
    }

    public void ChangePosition2()
    {
        // your operation
        SavePosition();
    }

    public void SavePosition()
    {
    }
}

看上面这个位置:
ChangePosition1 和 ChangePosition2

他们做完一些操作之后,需要做相同的操作,如上面所述,需要保存位置。

只有两个方法调用,那么不是啥子问题。

但是如果有大量的方法去调用这个东西,那么问题就出现了。

第一:重复性的工作
第二:出错率,每次都要写一遍,可能出现忘记的情况
第三:看着不优雅

那么在如此多的案例的情况下,人们都发现了规律。

比如说,在某个行为前做什么,在某个行为后做什么。

那么我们可以进行扩展:

public void Dosomething()
{
  // your operaion
}

aspect logging
{
   befor(dosomething is called)
   {
      Log.Write("enter dosomething")
   }

   after(dosomething is called)
   {
      Log.Write("after dosomething")
   }
}

aspect verification()
{
    befor(dosomething is called)
    {
      // your verification
    }
}

比如我们的验证和日志,可以通过这些aop去处理。

aop 全称是aspect-oriented programming 中文大多翻译过来是面向切面编程。

oriented 是面向,比如日志、验证,这些是aspect。

所以取了asepct-oriented programming 这个名字。

好的,那么现在了解了aop是什么东西,也了解了他的由来。

下面了解一下aop滥用的情况。

什么情况aop会滥用呢?

比如说:

public void setsomething()
{
}

aspect shutup
{
  after(something is called)
  {
    // shutup
  }
}

这种aop 就是反模式,不被推荐的。

原因是,比如我执行了setsomething之后,我setsomething 的意思是设置某一些东西,而没有shutup的含义。

但是最后却运行了该操作,这样难以维护和理解。

那么为什么logging 和 verification 能够被人所接受呢?

因为其没有破坏我们该代码的逻辑,的确setsomething做的事情就是它应该做的事情,不对执行逻辑造成影响。

深入一下aop是如何实现的呢?其实aop的原理很简单,但是优雅实现的却有一点点复杂。

  • 字节码操作

    • 优点:字节码操作可以在更细粒度的层面上操作代码,可以实现更灵活和精细的AOP功能。可以在编译期或运行期动态修改字节码,对目标类进行修改。
    • 缺点:实现相对复杂,需要对字节码结构有一定的了解。可能会影响代码的可读性和维护性。
  • 代理技术

    • 优点:代理技术相对简单易懂,可以快速实现AOP功能。可以通过代理对象来实现横切关注点的功能,不需要直接操作字节码。
    • 缺点:代理技术通常在运行时动态创建代理对象,可能会引入性能开销。对于一些高性能要求的场景,可能不太适合。

下面对这个分别进行举例:

先从好理解的代理开始:

public class LoggingAspect
{
    public void LogBefore(string methodName)
    {
        Console.WriteLine($"Logging before {methodName} execution");
    }
}

然后创建相应的代理:

public class UserServiceProxy<T> : DispatchProxy
{
    private T _decorated;
    
    private LoggingAspect _loggingAspect;
    
    protected override object? Invoke(MethodInfo? targetMethod, object?[]? args)
    {
        _loggingAspect.LogBefore(targetMethod.Name);
        
        return targetMethod.Invoke(_decorated, args);
    }
    
    public static T Create(T decorated)
    {
        object proxy = Create<T, UserServiceProxy<T>>();
        ((UserServiceProxy<T>)proxy)._decorated = decorated;
        ((UserServiceProxy<T>)proxy)._loggingAspect = new LoggingAspect();
        
        return (T)proxy;
    }
}

解释一下,这个create创建了什么,这个create 创建了两个类型的继承类。

也就是创建了动态类型。

public class UserService : IUserService
{
    public void Login()
    {
        Console.WriteLine("User logged in");
    }
}

现在是我们的代码实现了。

那么看下是怎么调用的。

public static void Main(string[] args)
{
    IUserService userService = new UserService();
    IUserService proxy = UserServiceProxy<IUserService>.Create(userService);
    proxy.Login();
}

这样就调用完成了。

看下效果。

这样就完成了相应的code。

至于为什么我们在使用框架的时候进行属性标记即可,那是因为框架帮我们把事情做了。

例如:

  1. 安装PostSharp:首先需要安装PostSharp NuGet包。

  2. 定义切面类

[Serializable]
public class LoggingAspect : OnMethodBoundaryAspect
{
    public override void OnEntry(MethodExecutionArgs args)
    {
        Console.WriteLine($"Logging before {args.Method.Name} execution");
    }
}
  1. 应用切面:在需要应用AOP的方法上添加切面标记。
public class UserService
{
    [LoggingAspect]
    public void Login()
    {
        Console.WriteLine("User logged in");
    }
}

至于这个框架是怎么实现的,原理就是利用MSBuilder。

MSBuild工具可以通过自定义任务(Custom Tasks)来实现预处理操作。通过编写自定义任务,可以在MSBuild构建过程中执行特定的预处理逻辑。以下是一个简单的示例,演示如何在MSBuild中使用自定义任务进行预处理:

  1. 创建自定义任务
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

public class CustomPreprocessTask : Task
{
    public override bool Execute()
    {
        // 在这里编写预处理逻辑
        Log.LogMessage("Custom preprocessing task executed.");
        return true;
    }
}
  1. 在项目文件中引用自定义任务

在项目文件(.csproj)中添加以下内容,引用自定义任务:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <UsingTask TaskName="CustomPreprocessTask" AssemblyFile="Path\\To\\CustomTask.dll" />
  
  <Target Name="CustomPreprocessTarget" BeforeTargets="Build">
    <CustomPreprocessTask />
  </Target>
</Project>
  1. 执行预处理操作

在构建项目时,MSBuild会执行自定义任务中定义的预处理逻辑。可以在Execute方法中编写任何需要的预处理代码,例如生成文件、修改配置等操作。

通过编写自定义任务并在项目文件中引用,可以利用MSBuild进行预处理操作。这样可以在构建过程中执行特定的逻辑,实现更灵活的构建流程。

代理模式,就是利用了msbuilder 预处理逻辑,在编译前进行了预处理。

那么字节码模式就是在msbuilder 编译后进行预处理。

using Mono.Cecil;
using Mono.Cecil.Cil;

public class LoggingAspect
{
    public void LogBefore()
    {
        Console.WriteLine("Logging before method execution");
    }
}

public class Program
{
    public static void Main()
    {
        AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly("YourAssembly.dll");
        ModuleDefinition module = assembly.MainModule;

        TypeDefinition type = module.Types.Single(t => t.Name == "UserService");
        MethodDefinition method = type.Methods.Single(m => m.Name == "Login");

        ILProcessor processor = method.Body.GetILProcessor();
        Instruction firstInstruction = method.Body.Instructions.First();

        // 在方法开头插入日志记录代码
        processor.InsertBefore(firstInstruction, processor.Create(OpCodes.Call, typeof(LoggingAspect).GetMethod("LogBefore")));

        assembly.Write("YourModifiedAssembly.dll");
    }
}

就是在我们程序编译完成后,进行在相应的位置进行注入程序。

下一节oop,关于aop解决一些实际问题的例子后续补齐。

标签:阶段性,自定义,void,public,概况,aop,class,预处理
From: https://www.cnblogs.com/aoximin/p/18134418

相关文章

  • 补档 荷兰留学概况一站式介绍_赵梦晨的博客_新东方前途出国
    荷兰留学概况一站式介绍_赵梦晨的博客_新东方前途出国 荷兰留学一站式介绍微资讯bygrace 2020-06-0718:45   美丽的郁金香之国-荷兰留学简介 国土面积:4.1万平方公里人口:1700万人政体:君主立宪制人均国民生产总值:5.3万美元,世界排名第十三位著名城......
  • 【Spring】AOP进阶-JoinPoint和ProceedingJoinPoint详解
    2024-04-141.前言在Spring AOP中,JoinPoint和ProceedingJoinPoint都是关键的接口,用于在切面中获取方法的相关信息以及控制方法的执行。它们的主要区别在于它们在AOP通知中的使用方式和功能。2.JoinPoint简介Joinpoint是面向切面编程(AOP)中的一个重要概念,指的是在应用程序执行......
  • 实现自定义注解校验方法参数(AOP+自定义注解+自定义异常+全局异常捕获)
    一、实现目的在编写接口的时候,通常会先对参数进行一次校验,这样业务逻辑代码就略显冗杂,如果可以把校验参数的代码进行统一管理,在方法或者属性上直接添加注解就可以实现参数的校验,就可以提升代码编写的效率。二、实现原理通过自定义注解,注解在入参VO的属性上,设定需要满足的条件,然......
  • AOP解析
    AOPbean准备1AOPsample1.1创建切面packagecom.gientech.aop.xml.util;importorg.aspectj.lang.JoinPoint;importorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.Signature;importjava.util.Arrays;publicclassLogUtil{publicvoid......
  • C#的AOP(最经典实现)
    (适用于.NET/.NETCore/.NETFramework)【目录】0.前言1.第一个AOP程序2.Aspect横切面编程3.一个横切面程序拦截多个主程序4.多个横切面程序拦截一个主程序5.AOP的泛型处理(扩充)6.AOP的异步处理(扩充)7.优势总结8.展望0.前言AOP(AspectOrientedProgramming)是“面向横切面编程”,主......
  • 采用自定义注解 和 AOP 完成日志记录
    1、声明一个自定义注解@Retention注解包含一个RetentionPolicy类型的属性value,用于指定注解的保留策略,常用的保留策略包括:RetentionPolicy.SOURCE:表示注解仅在源代码中保留,编译器编译时会将其忽略,不会保存在编译后的字节码中。RetentionPolicy.CLASS:表示注解在编译后的......
  • 【Spring】-Spring 之AOP注解
    目录Spring之AOP注解AOP思想:AOP的使用场景:@Aspect的使用以及基本概念:1.切面类2.切点@Pointcut3.Advice,4.JoinPoint:5.使用&&、||、!、三种运算符来组合切点表达式,表示与或非的关系;6.@annotation(annotationType)匹配指定注解为切入点的方法;具体代码实现:Spring之AOP注解A......
  • 韩国国际电池储能展览会2025KBS韩国电池储能产业概况
    韩国国际电池储能展览会2025KBS展会地点:韩国·高阳·韩国国际会展中心1(KINTEX1)主办单位:KoreaE&ExInc.五、韩国电池储能产业概况韩国的电池储能产业在全球范围内确实以其创新和高质量的产品而享有盛誉。-福贸展会大鹏zpexpo-近的一次韩国电池展览会(InterBattery2025)上,韩......
  • springboot3使用自定义注解+AOP+redis优雅实现防重复提交
     ⛰️个人主页:   蒾酒......
  • Spring AOP 技术详解
    学完AOP技术,真的不得不佩服发明AOP技术的人,真是个天才!!!想要了解AOP,首先要了解什么叫代理。1.代理我们先来说说什么叫做代理:        假如我要买辆奥迪A7,我不会直接去长春一汽工厂去买,为啥?路途远,而且,如果以这样方式购买,一手交钱,一手交车,事先没人给我介绍车辆配置情况......