Asp.NetCore 中Aop的应用
前言
其实好多项目中,做一些数据拦截、数据缓存都有Aop的概念,只是实现方式不一样;之前大家可能都会利用过滤器来实现Aop的功能,如果是Asp.NetCore的话,也可能会使用中间件; 而这种实现方式都是在请求过程中进行拦截,如果我们想在服务层中做切面的话,那种方式显然不好使了,需要用到“真正的Aop”。
直接开始
其实我们常说的“真正的Aop”其实就是动态代理,理论知识我这里就不记录了,自己也写不好,大家自行找度娘,我们这直接上代码:
正常搭建一个控制台项目,目录结构如下:

这里就是模拟一个简单的用户维护,代码内容如下:
定义Model
|
1
2
3
4
5
|
public class User { public string Name { get; set; } public int Age { get; set; } } |
定义接口
|
1
2
3
4
|
public interface IUserService { bool AddUser(User user); } |
实现接口
|
1
2
3
4
5
6
7
8
|
public class UserService : IUserService { public bool AddUser(User user) { Console.WriteLine("用户添加成功"); return true; } } |
main方法
|
1
2
3
4
5
6
7
8
9
10
11
|
class Program { static void Main(string[] args) { User user = new User {Name="Zoe", Age=18 }; IUserService userService = new UserService(); userService.AddUser(user); //Console.ReadLine(); } } |
项目很简单,正常运行就行;
新需求,如果我们想在用户增加前和增加后都做点其他事,怎么做呢?
解决方案:
1. 直接修改服务层代码,执行存储前后分别处理相关业务就行了;
2. 使用Aop,不修改原有方法。
方案1我们就不说了,肯定大家都知道,功能肯定能实现,但需要原有代码,加入好多接口都要处理类似的事情怎么办? 如果加好了,下个版本针对某些功能不需要了怎么办?显然不是很灵活,而且这样重复改,出Bug的几率很大哦!!!
直接动态代理:
1. 增加一个类,进行业务操作;
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
using System;using System.Collections.Generic;using System.Reflection;using System.Text;namespace Aop{ public class MyDecorator : DispatchProxy { //具体类型 public object TargetClass { get; set; } protected override object Invoke(MethodInfo targetMethod, object[] args) { Console.WriteLine("增加用户前执行业务"); //调用原有方法 targetMethod.Invoke(TargetClass, args); Console.WriteLine("增加用户后执行业务"); return true; } }} |
优化 Main()函数的代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
class Program { static void Main(string[] args) { User user = new User {Name="Zoe", Age=18 }; IUserService userService = new UserService(); userService.AddUser(user); //动态代理 //1. 创建代理对象 IUserService userService1 = DispatchProxy.Create<IUserService, MyDecorator>(); //2. 因为调用的是实例方法,需要传提具体类型 ((MyDecorator)userService1).TargetClass = new UserService(); userService1.AddUser(user); Console.ReadLine(); } } |
看动态代理部分,这样就统一实现了用户维护服务层的Aop编程,看运行结果:

这样是不是比较灵活了,自己不需要在一个个业务层中进行处理,而且取舍也很简单,不要就不适用此类就行了。
引用第三方库
原生的这种方式使用感觉有点麻烦,还有什么强制转换啊,传类型啊等这些,Castle.Core就帮我们把事都做好了,接下来我们看看怎么用。
1. 首先引入Castle.Core;
2. 新增拦截器类,做业务扩展;
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
using Castle.DynamicProxy;using System;using System.Collections.Generic;using System.Text;namespace Aop{ class MyIntercept : IInterceptor { public void Intercept(IInvocation invocation) { //执行原有方法之前 Console.WriteLine("增加用户前执行业务"); //执行原有方法 invocation.Proceed(); //执行原有方法之后 Console.WriteLine("增加用户后执行业务"); } }} |
3. Main函数增加Castle.Core的用法
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
using AopModel;using AopService;using Castle.DynamicProxy;using System;using System.Reflection;using System.Reflection.Metadata;namespace Aop{ class Program { static void Main(string[] args) { User user = new User {Name="Zoe", Age=18 }; IUserService userService = new UserService(); userService.AddUser(user); Console.WriteLine("=============动态代理=============="); //动态代理 //1. 创建代理对象 IUserService userService1 = DispatchProxy.Create<IUserService, MyDecorator>(); //2. 因为调用的是实例方法,需要传提具体类型 ((MyDecorator)userService1).TargetClass = new UserService(); userService1.AddUser(user); Console.WriteLine("=============Castle.Core=============="); ProxyGenerator generator = new ProxyGenerator(); var u = generator.CreateInterfaceProxyWithTarget<IUserService>(new UserService(),new MyIntercept()); u.AddUser(user); Console.ReadLine(); } }} |
这样就行了,看运行结果:

综上,第三方使用相对简单,而且封装了好多方法,不仅仅以上的使用方式。 以下举例集成Autofac和Castle.Core在Asp.NetCore中的应用(用Asp.NetCore项目,是因为好多真实项目都是API或Web项目,所以比较符合实际),仅供给大家提供思路。如下:
1. 首先我们创建一个Asp.NetCore项目,这里我创建的是API项目,正常运行即可,项目结构如下;

2. 引入三个包,通过Nuget安装,Autofac开头,如下

注: 其中Autofac.Extras.DynamicProxy就是AOP相关组件,其中包含了Castle.Core,所以不用单独安装Castle.Core.
3.模拟编写用户维护相关逻辑,代码如下:
接口:
|
1
2
3
4
|
public interface IUserService { int AddUser(string strName, int nAge); } |
实现:
|
1
2
3
4
5
6
7
8
9
10
11
|
public class UserService : IUserService { /// <summary> /// 模拟新增用户,这里没有写数据处理层 /// </summary> public int AddUser(string strName, int nAge) { Console.WriteLine("新增用户到数据库中"); return 1; } } |
4. 编写拦截器逻辑,即代理:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
using Castle.DynamicProxy;using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;namespace WebAop.Aop{ public class UserAop : IInterceptor { //关键所在,在执行方法前后进行相关逻辑处理 public void Intercept(IInvocation invocation) { Console.WriteLine("新增用户前进行其他处理"); //调用原有方法 invocation.Proceed(); Console.WriteLine("新增用户后进行其他处理"); } }} |
5. 集成Autofac将用户维护服务这块进行注册到容器中:
- 首先在Startup中增加方法,如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public void ConfigureContainer(ContainerBuilder builder) { //注册用户维护业务层 var basePath = AppContext.BaseDirectory; var serviceDll = Path.Combine(basePath, "AopService.dll"); if(!File.Exists(serviceDll)) { throw new Exception("找不到程序集"); } //注册AOP拦截器 builder.RegisterType(typeof(UserAop)); builder.RegisterAssemblyTypes(Assembly.LoadFrom(serviceDll)) .AsImplementedInterfaces() .EnableInterfaceInterceptors()//开启切面,需要引入Autofac.Extras.DynamicProxy .InterceptedBy(typeof(UserAop));//指定拦截器,可以指定多个 } |
- 然后在program中添加Autofac的工厂,如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using Autofac.Extensions.DependencyInjection;using Microsoft.AspNetCore.Hosting;using Microsoft.Extensions.Configuration;using Microsoft.Extensions.Hosting;using Microsoft.Extensions.Logging;namespace WebAop{ public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) //需要引入Autofac.Extensions.DependencyInjection, 这里重要,不然Autofac不管用 .UseServiceProviderFactory(new AutofacServiceProviderFactory()) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); }} |
6. 增加UserController方法,如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using AopService.Interface;using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Mvc;namespace WebAop.Controllers{ [Route("api/[controller]")] [ApiController] public class UserController : ControllerBase { private IUserService _userService; <strong> //这里已经通过Autofac 注册过了,直接通过构造函数注入即可 public UserController(IUserService userService) { _userService = userService; }</strong> [HttpGet] [Route("AddUser")] public IActionResult AddUser(string name,int age) { <strong> //正常调用用户新增操作 _userService.AddUser(name, age);</strong> return Ok("Success!!"); } }} |
7. 运行走起,为了方便看见控制台打印,用项目启动方式进行运行,结果如下:
直接在浏览器中输入http://localhost:5000/api/User/AddUser?name=sss&age=12,然后回车,然后看控制台打印:

总结:
AOP在做一些业务前置或后置处理上时很有用的,使用比较灵活,无需修改原有代码逻辑,比起修改原有代码维护相对好多啦!!!
Asp.NetCore 中Aop的应用的更多相关文章
- AutoMapper在asp.netcore中的使用
# AutoMapper在asp.netcore中的使用 automapper 是.net 项目中针对模型之间转换映射的一个很好用的工具,不仅提高了开发的效率还使代码更加简洁,当然也是开源的,htt ...
- SignalR在Asp.NetCore中的使用
SignalR简介 ASP.NET SignalR是为ASP.NET 开发人员提供的一个库,旨在为你的Web应用迅速简便的添加实时通信功能.这个Web通信功能是指:客户端可以实时从服务端代码拉取数据, ...
- 壹佰文章最全总结| 《关于ASP.NETCore的分享之路》
学习路线图 (关于学习ASP.NET Core需要了解和掌握的知识点图) 一言不合就来图,各位博客园小伙伴大家好,感觉好久没有写文章了,自从春节开始,中间经历种种,慢慢的就开始微信公众号发文了,原因有 ...
- asp.netcore 深入了解配置文件加载过程
前言 配置文件中程序运行中,担当着不可或缺的角色:通常情况下,使用 visual studio 进行创建项目过程中,项目配置文件会自动生成在项目根目录下,如 appsettings.json, ...
- ASP.NETCore学习记录(一)
ASP.NETCore学习记录(一) asp.net core介绍 Startup.cs ConfigureServices Configure 0. ASP.NETCore 介绍 ASP.N ...
- Asp.NetCore源码学习[2-1]:配置[Configuration]
Asp.NetCore源码学习[2-1]:配置[Configuration] 在Asp. NetCore中,配置系统支持不同的配置源(文件.环境变量等),虽然有多种的配置源,但是最终提供给系统使用的只 ...
- Asp.NetCore Web开发之会话技术
这节讲一下会话技术,首先了解一下什么是会话,会话是指浏览器打开到关闭的过程中,多次与服务器发送接收数据的过程. 由于HTTP是无状态协议,一次请求响应过后,产生的数据就随之释放了,可是在某些情况下,我 ...
- .netcore 中使用开源的AOP框架 AspectCore
AspectCore Project 介绍 什么是AspectCore Project ? AspectCore Project 是适用于Asp.Net Core 平台的轻量级 Aop(Aspect- ...
- asp.netMVC中使用aop进行关注点分离
资源地址:https://stackoverflow.com/questions/23244400/aspect-oriented-programming-in-asp-net-mvc 从页面复制过来 ...
随机推荐
- 一文读懂 .NET 中的高性能队列 Channel
介绍 System.Threading.Channels 是.NET Core 3.0 后推出的新的集合类型, 具有异步API,高性能,线程安全等特点,它可以用来做消息队列,进行数据的生产和消费, 公 ...
- python + pytest基本使用方法(运行测试&测试报告)
import pytest# 1.运行名称中包含某字符串的测试用例#名称中含add 的测试用例# 执行: pytest -k add test_assert.py# 2.减少测试的运行冗长# 执行: ...
- 医疗器械软件产品经理必读的法规及标准-YY/T0664(二)
上节主要讲了软件开发策划.软件需求分析.软件系统结构设计三个阶段,这节来分析以下几个阶段. 1.软件单元实现 2.软件集成和集成测试 3.软件系统测试 软件开发过程由若干个活动组成,主要包括软件开发策 ...
- 【搜索】棋盘 luogu-3956
分析 按照这个题目随便写一个搜索就可以了 AC代码 #include <cstdio> #include <cstring> #include <algorithm> ...
- TCP通信简单梳理
一.什么是TCP协议 TCP协议是一种面向连接的可靠的通信协议,最重要的两个特点:连接.可靠. 二.TCP是如何进行通信的 TCP通过三次握手建立连接后客户端服务端的内核都分别开辟资源,这时候开始进行 ...
- leetcode 有效三角形的个数
题目描述: 平明伞兵解法: 既然要求满足三角形要求的三边,简单来说,就是最短两边之和大于第三边,所以,第一步Arrays.sort().先排序,然后直接伞兵暴力法,三重循环.当然最后肯定是能跑出来的, ...
- Mybatis学习笔记导航
Mybatis小白快速入门 简介 本人是一个Java学习者,最近才开始在博客园上分享自己的学习经验,同时帮助那些想要学习的uu们,相关学习视频在小破站的狂神说,狂神真的是我学习到现在觉得最GAN的老师 ...
- 使用 GLFW 在 OpenGL 的场景中漫游
前言 前面已经建立了 OpenGL 框架,加载了 3D 模型,但是还没有在场景中漫游的功能.为了展示 3D 模型,我只是简单地利用变换视图矩阵的方式使模型在视野中旋转.同时,之前的程序连最简单的改变窗 ...
- Thunder DLL Hijacking
简记 原理基础啥的俺也不写了 1.寻找DLL 生成恶意dll文件 拿calc测试 2.放入 3.打开
- webservice接口调用
package com.montnets.emp.sysuser.biz; import org.apache.axis.client.Call; import org.apache.axis.cli ...