NCoreCoder.Aop详解
于今天,功能终于完善度到比较满意的程度了
准备好好写一篇文章,而不是之前的流水账,分享一下最近这些天的踩坑
一开始AOP选的微软提供的DispatchProxy
关于这个,有大佬的文章,可以看看,了解一下
初步完成后,发现几个大问题,异步不支持,不支持构造器注入,代理类必须是继承DispatchProxy的公开类
我就想到我偶像Lemon大佬的著作AspectCore了,依稀记得是Emit构建的代理类
也有代码可以参考学习,那就开干,前后四天多的时间,终于完工
下面介绍一下我的AOP组件 NCoreCoder.Aop的使用以及高级应用
简单的使用NCoreCoder.Aop
NCoreCoder.Aop支持依赖注入,用依赖注入的方式完成代理类和接口的关联
支持.Net Core 3.0以及以下的依赖注入方式
示例
public interface IMyClass
{
void TestVoid();
int TestInt();
Task TestAsync();
Task<int> TestIntAsync();
} [JitInject]
internal class MyClass : IMyClass
{
public void TestVoid()
{
Console.WriteLine("TestVoid");
} public int TestInt()
{
Console.WriteLine("TestInt"); return ;
} public Task TestAsync()
{
Console.WriteLine("TestAsync"); return Task.CompletedTask;
} public Task<int> TestIntAsync()
{
Console.WriteLine("TestIntAsync"); return Task.FromResult();
}
}
打上JitInject特性是证明这个类需要实现代理
这里就只是构建代理类,没有方法并走代理流程,代理支持 同步API、异步无返回值API、异步有返回值API
要拦截的方法,默认是继承JitAopAttribute,打特性方式完成拦截器注入
打在继承的实现类上
比如
[AttributeUsage(AttributeTargets.Method)]
internal class TestJitAttribute : JitAopAttribute
{
public override void Before(MethodReflector method, object instance, params object[] param)
{
} public override void After(MethodReflector method, object instance, params object[] param)
{
} public override Task BeforeAsync(MethodReflector method, object instance, params object[] param)
{return Task.CompletedTask;
} public override Task AfterAsync(MethodReflector method, object instance, params object[] param)
{return Task.CompletedTask;
}
}
在需要拦截的方法上,打上TestJit即可
[TestJit]
public void TestVoid()
{
Console.WriteLine("TestVoid");
} public int TestInt()
{
Console.WriteLine("TestInt"); return ;
} public Task TestAsync()
{
Console.WriteLine("TestAsync"); return Task.CompletedTask;
} public Task<int> TestIntAsync()
{
Console.WriteLine("TestIntAsync"); return Task.FromResult();
}
}
这样TestVoid方法就要走AOP流程了
Asp.Net Core 3.0以下
因为Asp.Net Core 3.0以下的Startup.ConfigService方法支持直接修改返回值变成IServiceProvider
所以在Asp.Net Core 3.0以下,依赖注入都是在Startup.ConfigService里面修改IServiceProvider到自定义的IServiceProvider完成替换依赖注入容器和流程的效果,比如Autofac
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
//略略略
}
改为
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc();
//略略略
service.AddSingleton<IMyClass, MyClass>(); //修改Ioc容器流程
return service.BuilderJit();
}
Asp.Net Core 3.0
Asp.Net Core 3.0的替换依赖注入流程变了
无法再修改Startup.ConfigService返回值了,只要不是void,运行就抛出异常
查看的Program.CreateHostBuilder
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
改为
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new JitServiceProviderFactory()) //新增
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
这里可以保持原有依赖注入,也可以增加一个方法
public void ConfigureContainer(JitAopBuilder builder)
{
builder.Add<IMyClass, MyClass>(ServiceLifetime.Singleton);
}
测试Aop
var service = new ServiceCollection(); service.AddSingleton<IMyClass, MyClass>(); var serviceProvider = service.BuilderJit(); TypeBuilderFactory.Instance.Save(); var myclass = serviceProvider.GetRequiredService<IMyClass>(); Task.Factory.StartNew(async () =>
{
myclass.TestVoid();
var result1 = myclass.TestInt(); await myclass.TestAsync();
var result2 = await myclass.TestIntAsync();
}); Console.ReadLine();
我们运行看看myclass对象是什么~
不是原有的MyClass对象
高级扩展
我们现在如果要针对不同流程,而不是默认的Before->After
那么我们就需要自定义一个IAopActors了
我们默认的JitAopAttribute的流程就是一个默认DefaultAopActors
编写一个公开的类,继承自IAopActors
IAopActors接口如下
然后再接口上打上特性AopActorsAttribute
特性的构造参数是Type对应了自定义的AopActors的Type
public class TestActors : IAopActors
{
public object Execute(AopContext context)
{
throw new NotImplementedException();
} public Task<TResult> ExecuteAsync<TResult>(AopContext context)
{
throw new NotImplementedException();
} public Task InvokeAsync(AopContext context)
{
throw new NotImplementedException();
}
}
[AopActors(typeof(TestActors))]
public interface IMyClass
{
void TestVoid();
int TestInt();
Task TestAsync();
Task<int> TestIntAsync();
}
个人文笔不好,如有疑问,可以加“.Net应用程序框架交流” 群号386092459 欢迎到群里和我反馈Bug或者建议、交流Aop设计和Emit的知识
NCoreCoder.Aop详解的更多相关文章
- Spring4 AOP详解
Spring4 AOP详解 第一章Spring 快速入门并没有对Spring4 的 AOP 做太多的描述,是因为AOP切面编程概念不好理解.所以这章主要从三个方面详解AOP:AOP简介(了解),基于注 ...
- 【转载】Spring AOP详解 、 JDK动态代理、CGLib动态代理
Spring AOP详解 . JDK动态代理.CGLib动态代理 原文地址:https://www.cnblogs.com/kukudelaomao/p/5897893.html AOP是Aspec ...
- [Spring学习笔记 5 ] Spring AOP 详解1
知识点回顾:一.IOC容器---DI依赖注入:setter注入(属性注入)/构造子注入/字段注入(注解 )/接口注入 out Spring IOC容器的使用: A.完全使用XML文件来配置容器所要管理 ...
- AOP 详解
1. 需求:统计方法执行的性能情况(来源:<精通Spring 4.x>) // 性能监视类 PerformanceMonitor package com.noodles.proxy; pu ...
- Spring AOP详解(转载)所需要的包
上一篇文章中,<Spring Aop详解(转载)>里的代码都可以运行,只是包比较多,中间缺少了几个相应的包,根据报错,几经百度搜索,终于补全了所有包. 截图如下: 在主测试类里面,有人怀疑 ...
- Spring AOP详解及简单应用
Spring AOP详解 一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址: ...
- 转:Spring AOP详解
转:Spring AOP详解 一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址: ...
- Spring全家桶——SpringBoot之AOP详解
Spring全家桶--SpringBoot之AOP详解 面向方面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP). OOP中模块化的关键单元是类,而在AOP中,模块化单元是方 ...
- Spring Aop 详解二
这是Spring Aop的第二篇,案例代码很详解,可以查看https://gitee.com/haimama/java-study/tree/master/spring-aop-demo. 阅读前,建 ...
随机推荐
- BUUCTF-Crypyo-No.1
我我我我我又来惹~~~~* MD5 flag{admin1} 看我回旋踢 凯撒密码 flag{5cd1004d-86a5-46d8-b720-beb5ba0417e1} Url编码 flag{and ...
- 线下---复习day04---作业
1 学的不好的同学:用ajax提交一个json格式数据,返回一个json格式数据,console.log打印出来 2 通过ajax上传一个文件并保存起来,前端接收到,弹窗说上传成功 urls.py f ...
- docker安装,卸载和入门
Docker 简介 背景 开发和运维之间因为环境不同而导致的矛盾 集群环境下每台机器部署相同的应用 DevOps(Development and Operations) 简介 Docker是一个开源的 ...
- display:inline-block 什么时候不会显示间隙?
移除空格 使用margin负值 使用font-size:0 letter-spacing word-spacing
- Odoo13之在tree视图左上角添加自定义按钮
前言 首先展示效果图,如下图所示,在资产设备模块tree视图的左上角添加了一个同步资产的按钮. 要完成按钮的添加,分为四步,分别是: 1.编写xml文件,找到相关模型tree视图,并给模型tree视图 ...
- “我放弃了年薪20W的offer......”
我的职业生涯开始和大多数测试人一样,开始接触都是纯功能界面测试.那时候在一家电商公司做测试,做了有一段时间,熟悉产品的业务流程以及熟练测试工作流程规范之后,效率提高了,工作比较轻松,也得到了更好的机会 ...
- Oracle DataGuard主备切换(switchover)
Oracle DataGuard主备切换可以使用传统的手动命令切换,也可以使用dgmgr切换,本文记录手动切换. (一)将主库切换为物理备库 STEP1:查看主库状态 SQL> SELECT O ...
- html命名规则
CSS样式命名 外套 wrap ------------------用于最外层 头部 header ----------------用于头部 主要内容 main ------------用于主体内容( ...
- elementUI form表单验证不通过的原因
<el-form :model="form" :rules="rules"> <el-form-item prop="input&q ...
- python dict乱码如何解决
定义字典并直接输出,结果输出结果中文是乱码展示 d={'name':'lily','age':18,'sex':'女','no':1121} print d 输出结果: {'age': 18, 'no ...