NetCore环境下的AOP程序拦截主程序

主机推荐网 296 0

1.第一个AOP程序

制作一个AOP程序需要四个步骤:

(1)制作主程序

(2)制作横切面程序

(3)制作配置文件,让横切面程序拦截主程序

(4)调用主程序

下面,我们一步一步来实现上述四个步骤。

【第一步】:制作主程序

我们在 中新建一个名为“.Logic”的类库工程,并在该工程中新建一个名为的类,该类中有一个名为的方法,代码如下:

//从NuGet引用DeveloperSharp包using DeveloperSharp.Structure.Model;
namespace School.Logic{ //主程序必须继承自LogicLayer类 public class PersonManage : LogicLayer { public string GetInfo1(string Name, int Num) { return $"共有{Name}{Num}人"; } }}

以上,编写了一个非常简单的主程序。

【第二步】:制作横切面程序

我们再在 中新建一个名为“.”的类库工程,并在该工程中新建一个名为的类,代码如下:

//从NuGet引用DeveloperSharp包using DeveloperSharp.Structure.Model.Aspect;
namespace School.Aspect{ //横切面程序必须继承自AspectModel类 public class Interceptor1 : AspectModel { //PreProcess方法先于主程序执行 public override void PreProcess(object sender, AspectEventArgs e) { //把主程序的两个参数值改掉 e.MethodInfo.ParameterValues[0] = "老师"; e.MethodInfo.ParameterValues[1] = 20; }
//PostProcess方法后于主程序执行 public override void PostProcess(object sender, AspectEventArgs e) {
} }}

以上,编写了一个横切面程序。它的主要功能是把主程序方法的两个参数值给改掉。

【第三步】:制作配置文件,让横切面程序拦截主程序

若是在.Net Core环境下,我们创建一个名为.json的配置文件,设置让拦截中的方法。文件内容如下:

{  "DeveloperSharp":  {     "AspectObject":     [         {           "name":"School.Aspect.Interceptor1",  //横切面拦截器类           "scope":"School.Logic.PersonManage",  //被拦截的主程序类           "method":"GetInfo1"                   //被拦截的方法         }     ]  }}

若是在.Net 环境下,我们创建一个名为.xml的配置文件,设置让拦截中的方法。文件内容如下:

<DeveloperSharp>  <AspectObject>    <Ao name="School.Aspect.Interceptor1" scope="School.Logic.PersonManage" method="GetInfo1"/>  AspectObject>DeveloperSharp>

注意:以上配置中所有的类名,都要用完全限定名。

【第四步】:调用主程序

最后,我们再在 中创建一个控制台工程,让它来调用主程序中的方法,代码如下:

        //需要引用School.Aspect、School.Logic、DeveloperSharp三项        static void Main(string[] args)        {            var pm = new School.Logic.PersonManage();
//要用这种形式调用主程序中的方法,AOP功能才会生效 var str = pm.InvokeMethod("GetInfo1", "学生", 200); Console.WriteLine(str);
Console.ReadLine(); }

为了让前面第三步创建的配置文件生效,我们此时还需要在此主调项目中对它进行链接:

若是在.Net Core环境下,我们只需要把.json文件放到程序执行目录中(即bin目录下与dll、exe等文件的同一目录中,放错了位置会报错)(注意:有些.Net Core版本在 “调试”时,不会在bin目录下生成全部的dll、exe,此时需要把此配置文件放在应用程序的“根目录”下)。

若是在.Net 环境下,我们需要在工程配置文件App./Web.中添加节点,节点内容如下:

  <appSettings>    <add key="ConfigFile" value="D:\Test\Assist\DeveloperSharp.xml" />  appSettings>

此处需要设置为配置文件的“绝对路径”(使用“绝对路径”而不是“相对路径”,一是有利于安全性,二是有利于分布式部署)

一切准备完毕,运行,结果如下:

【控制台显示出】:共有老师20人

可见AOP已经拦截成功。

若此时,我们在配置文件.json/.xml中稍做修改,比如:把“”这个方法名改为“ABC”这样一个不存在的方法名,再运行,结果如下:

【控制台显示出】:共有学生200人

注意:使用平台的AOP技术,主程序类库名必须以Logic结尾(本篇为:.Logic),横切面程序类库名必须以结尾(本篇为:.),且这两个名字的其它部分要完全一样。这是一个特别限定条件!

2.横切面编程

上面,第二步,制作的横切面程序,是通过修改主程序方法的参数值,而最终改变了主程序的返回值。

其实,我们也有办法直接修改主程序方法的返回值,比如把上面类的代码修改为如下:

//从NuGet引用DeveloperSharp包using DeveloperSharp.Structure.Model.Aspect;
namespace School.Aspect{ //横切面程序必须继承自AspectModel类 public class Interceptor1 : AspectModel { //PreProcess方法先于主程序执行 public override void PreProcess(object sender, AspectEventArgs e) {
}
//PostProcess方法后于主程序执行 public override void PostProcess(object sender, AspectEventArgs e) { //把主程序的返回值改掉 e.MethodInfo.ReturnValue = $"共有校长2人"; } }}

运行,结果如下:

【控制台显示出】:共有校长2人

到目前为止,我们已经知道了如何通过“横切面程序”修改主程序方法的参数值、返回值。

如果我们想进一步获取主程序的“命名空间”、“类名”、“方法名”、“参数名”、“参数类型”、“返回值类型”,则可以通过如下代码获取:

e.MethodInfo.NamespaceName                       //命名空间e.MethodInfo.ClassName                           //类名e.MethodInfo.MethodName                          //方法名e.MethodInfo.ParameterInfos[0].Name              //参数名(第一个参数)e.MethodInfo.ParameterInfos[0].ParameterType     //参数类型(第一个参数)e.MethodInfo.ReturnValue.GetType()               //返回值类型

有时候,在某些特殊情况下,我们希望主程序方法不运行,此时则可以通过在方法里把e.设置为false来完成。

接前面的“第一个AOP程序”,比如:我们希望当人数大于10000时,主程序方法就不再运行,则可以通过把类的代码修改为如下样式来实现:

//从NuGet引用DeveloperSharp包using DeveloperSharp.Structure.Model.Aspect;
namespace School.Aspect{ //横切面程序必须继承自AspectModel类 public class Interceptor1 : AspectModel { //PreProcess方法先于主程序执行 public override void PreProcess(object sender, AspectEventArgs e) { //当人数大于10000时,主程序方法就不再运行 if (Convert.ToInt32(e.MethodInfo.ParameterValues[1]) > 10000) e.Continue = false; }
//PostProcess方法后于主程序执行 public override void PostProcess(object sender, AspectEventArgs e) {
} }}

现在的这个示例是一个横切面程序拦截一个主程序。在后续将要讲解的“多个横切面程序拦截一个主程序”的情况中,只要有一个e.=false被设置,主程序方法就不会运行(在此事先提点)。

3.一个横切面程序拦截多个主程序

为了演示这部分的内容,我们首先在前面“第一个AOP程序”的基础上,把主程序进行扩充。采取的动作是:

(1)在类中增加一个方法

(2)再新增一个主程序类,该类中有一个名为的方法。代码如下:

类:

//从NuGet引用DeveloperSharp包using DeveloperSharp.Structure.Model;
namespace School.Logic{ //主程序必须继承自LogicLayer类 public class PersonManage : LogicLayer { public string GetInfo1(string Name, int Num) { return $"共有{Name}{Num}人"; }
public string GetInfo2(string Name, int Num) { return $"学校共有{Name}{Num}人"; } }}

类:

//从NuGet引用DeveloperSharp包using DeveloperSharp.Structure.Model.Aspect;
namespace School.Aspect{ //横切面程序必须继承自AspectModel类 public class Interceptor1 : AspectModel { //PreProcess方法先于主程序执行 public override void PreProcess(object sender, AspectEventArgs e) { //把主程序的两个参数值改掉 e.MethodInfo.ParameterValues[0] = "老师"; e.MethodInfo.ParameterValues[1] = 20; }
//PostProcess方法后于主程序执行 public override void PostProcess(object sender, AspectEventArgs e) {
} }}0

如此一来,现在就有了3个主程序方法。

接下来,我们修改配置文件,让去拦截上述的3个主程序方法。

若是在.Net Core环境下,.json文件的内容修改为如下:

//从NuGet引用DeveloperSharp包using DeveloperSharp.Structure.Model.Aspect;
namespace School.Aspect{ //横切面程序必须继承自AspectModel类 public class Interceptor1 : AspectModel { //PreProcess方法先于主程序执行 public override void PreProcess(object sender, AspectEventArgs e) { //把主程序的两个参数值改掉 e.MethodInfo.ParameterValues[0] = "老师"; e.MethodInfo.ParameterValues[1] = 20; }
//PostProcess方法后于主程序执行 public override void PostProcess(object sender, AspectEventArgs e) {
} }}1

若是在.Net 环境下,.xml文件的内容修改为如下:

//从NuGet引用DeveloperSharp包using DeveloperSharp.Structure.Model.Aspect;
namespace School.Aspect{ //横切面程序必须继承自AspectModel类 public class Interceptor1 : AspectModel { //PreProcess方法先于主程序执行 public override void PreProcess(object sender, AspectEventArgs e) { //把主程序的两个参数值改掉 e.MethodInfo.ParameterValues[0] = "老师"; e.MethodInfo.ParameterValues[1] = 20; }
//PostProcess方法后于主程序执行 public override void PostProcess(object sender, AspectEventArgs e) {
} }}2

最后,我们把控制台启动程序修改为如下:

//从NuGet引用DeveloperSharp包using DeveloperSharp.Structure.Model.Aspect;
namespace School.Aspect{ //横切面程序必须继承自AspectModel类 public class Interceptor1 : AspectModel { //PreProcess方法先于主程序执行 public override void PreProcess(object sender, AspectEventArgs e) { //把主程序的两个参数值改掉 e.MethodInfo.ParameterValues[0] = "老师"; e.MethodInfo.ParameterValues[1] = 20; }
//PostProcess方法后于主程序执行 public override void PostProcess(object sender, AspectEventArgs e) {
} }}3

运行结果如下:

【控制台显示出】:

共有老师20人

学校共有老师20人

第一组共有老师20人,第二组共有院士10人

可见AOP所有拦截均已成功!

4.多个横切面程序拦截一个主程序

为了演示这部分的内容,我们还是要先回到前面的“第一个AOP程序”,在它的基础上,我们新增一个名为的横切面类,代码如下:

//从NuGet引用DeveloperSharp包using DeveloperSharp.Structure.Model.Aspect;
namespace School.Aspect{ //横切面程序必须继承自AspectModel类 public class Interceptor1 : AspectModel { //PreProcess方法先于主程序执行 public override void PreProcess(object sender, AspectEventArgs e) { //把主程序的两个参数值改掉 e.MethodInfo.ParameterValues[0] = "老师"; e.MethodInfo.ParameterValues[1] = 20; }
//PostProcess方法后于主程序执行 public override void PostProcess(object sender, AspectEventArgs e) {
} }}4

如此一来,我们就有了2个横切面程序与。

接下来,我们修改配置文件,让、都去拦截主程序方法。

若是在.Net Core环境下,.json文件的内容修改为如下:

//从NuGet引用DeveloperSharp包using DeveloperSharp.Structure.Model.Aspect;
namespace School.Aspect{ //横切面程序必须继承自AspectModel类 public class Interceptor1 : AspectModel { //PreProcess方法先于主程序执行 public override void PreProcess(object sender, AspectEventArgs e) { //把主程序的两个参数值改掉 e.MethodInfo.ParameterValues[0] = "老师"; e.MethodInfo.ParameterValues[1] = 20; }
//PostProcess方法后于主程序执行 public override void PostProcess(object sender, AspectEventArgs e) {
} }}5

若是在.Net 环境下,.xml文件的内容修改为如下:

//从NuGet引用DeveloperSharp包using DeveloperSharp.Structure.Model.Aspect;
namespace School.Aspect{ //横切面程序必须继承自AspectModel类 public class Interceptor1 : AspectModel { //PreProcess方法先于主程序执行 public override void PreProcess(object sender, AspectEventArgs e) { //把主程序的两个参数值改掉 e.MethodInfo.ParameterValues[0] = "老师"; e.MethodInfo.ParameterValues[1] = 20; }
//PostProcess方法后于主程序执行 public override void PostProcess(object sender, AspectEventArgs e) {
} }}6

上述修改完毕,运行控制台主调程序,结果如下:

【控制台显示出】:共有辅导员40人

从上述运行结果,我们大致可以推断出:、这两个横切面拦截器是按配置顺序执行的。其中,先把方法的两个参数值改为了("老师",20),接着,又把方法的两个参数值改为了("辅导员",40),所以最终方法的参数值变为了("辅导员",40)。

5.优势总结

本文所讲述的,是全网唯一实现AOP彻底解耦的技术方案。使用它,当你需要给主程序增加横切面拦截器时,无论是增加一个还是多个,都不再需要修改&重新编译主程序。这实现了不同功能构件之间的0依赖拼装/拆卸开发方式,随之而来的也会对研发团队的管理模式产生重大影响,意义深远...

6.展望

AOP对于程序代码的解耦、业务模块的拆分与拼装组合,有着巨大的作用。正确的使用AOP,甚至能对传统的软件架构设计,产生颠覆性的影响,如超级战士出场一般,让所有人刮目相看,完全耳目一新!!

为了让读者能直观感知AOP的上述神奇魅力,下面给出一个业务案例:

有一批货品要录入数据库,货品包含长、宽、高、颜色、类型等属性。现在有业务需求如下,

(1)当货品长度大于10厘米时,它在数据库中标记为A类;当货品长度大于20厘米时,标记为B类。

(2)当货品颜色无法分辨时,统一在数据库中默认标记为白色。

(3)每个货品录入数据库后,还要在另一个财务数据库中录入该货品的价格信息,同时把该货品的操作员名字记入日志文件。

这样的一个业务案例,你以前会怎么设计这个程序?今天学了AOP后你又会怎么设计程序?你会创建几个横切面了...?

所属专题: 程序 拦截 货品 辅导 标记

发布评论 0条评论)

  • Refresh code

还木有评论哦,快来抢沙发吧~