Autofac的切面编程实现
面向切面编程:Autofac.Annotation扩展组件是我开源的一款利用打标签完成autofac容器的注入组件。
https://github.com/yuzd/Autofac.Annotation
我们之前介绍了利用Aspect标签来完成拦截器功能
Aspect是一对一的方式,我想要某个class开启拦截器功能我需要针对每个class去配置。 详情请点击
比如说 我有2个 controller 每个controller都有2个action方法,
[Component]public class ProductController{public virtual string GetProduct(string productId){return "GetProduct:" + productId;}public virtual string UpdateProduct(string productId){return "UpdateProduct:" + productId;}}[Component]public class UserController{public virtual string GetUser(string userId){return "GetUser:" + userId;}public virtual string DeleteUser(string userId){return "DeleteUser:" + userId;}}
如果我需要这2个controller的action方法都在执行方法前打log 在方法执行后打log 按照上一节Aspect的话 我需要每个controller都要配置。如果我有100个controller的画我就需要配置100次,这样我觉得太麻烦了。所以我参考了Spring的Pointcut切面编程的方式实现了一套类似的,下面看如何用Pointcut的方式方便的配置一种切面去适用于N个对象。
定义一个切面:创建一个class 上面打上Pointcut的标签 如下:
Pointcut标签类有如下属性:
属性名 | 说明 |
---|---|
Name | 名称Pointcut切面的名称(默认为空,和拦截方法进行匹配,参考下面说明) |
RetType | 匹配目标类的方法的返回类型(默认是%) |
NameSpace | 匹配目标类的namespace(默认是%) |
ClassName | 匹配目标类的类名称(必填) |
MethodName | 匹配目标类的方法名称(默认是%) |
匹配算法
举例:
匹配结果 | 匹配模板 | 要匹配的字符串 |
---|---|---|
匹配结果:true | "%" | "" |
匹配结果:true | "%" | " " |
匹配结果:true | "%" | "asdfa asdf asdf" |
匹配结果:true | "%" | "%" |
匹配结果:false | "_" | "" |
匹配结果:true | "_" | " " |
匹配结果:true | "_" | "4" |
匹配结果:true | "_" | "C" |
匹配结果:false | "_" | "CX" |
匹配结果:false | "[ABCD]" | "" |
匹配结果:true | "[ABCD]" | "A" |
匹配结果:true | "[ABCD]" | "b" |
匹配结果:false | "[ABCD]" | "X" |
匹配结果:false | "[ABCD]" | "AB" |
匹配结果:true | "[B-D]" | "C" |
匹配结果:true | "[B-D]" | "D" |
匹配结果:false | "[B-D]" | "A" |
匹配结果:false | "[^B-D]" | "C" |
匹配结果:false | "[^B-D]" | "D" |
匹配结果:true | "[^B-D]" | "A" |
匹配结果:true | "%TEST[ABCD]XXX" | "lolTESTBXXX" |
匹配结果:false | "%TEST[ABCD]XXX" | "lolTESTZXXX" |
匹配结果:false | "%TEST[^ABCD]XXX" | "lolTESTBXXX" |
匹配结果:true | "%TEST[^ABCD]XXX" | "lolTESTZXXX" |
匹配结果:true | "%TEST[B-D]XXX" | "lolTESTBXXX" |
匹配结果:true | "%TEST[^B-D]XXX" | "lolTESTZXXX" |
匹配结果:true | "%Stuff.txt" | "Stuff.txt" |
匹配结果:true | "%Stuff.txt" | "MagicStuff.txt" |
匹配结果:false | "%Stuff.txt" | "MagicStuff.txt.img" |
匹配结果:false | "%Stuff.txt" | "Stuff.txt.img" |
匹配结果:false | "%Stuff.txt" | "MagicStuff001.txt.img" |
匹配结果:true | "Stuff.txt%" | "Stuff.txt" |
匹配结果:false | "Stuff.txt%" | "MagicStuff.txt" |
匹配结果:false | "Stuff.txt%" | "MagicStuff.txt.img" |
匹配结果:true | "Stuff.txt%" | "Stuff.txt.img" |
匹配结果:false | "Stuff.txt%" | "MagicStuff001.txt.img" |
匹配结果:true | "%Stuff.txt%" | "Stuff.txt" |
匹配结果:true | "%Stuff.txt%" | "MagicStuff.txt" |
匹配结果:true | "%Stuff.txt%" | "MagicStuff.txt.img" |
匹配结果:true | "%Stuff.txt%" | "Stuff.txt.img" |
匹配结果:false | "%Stuff.txt%" | "MagicStuff001.txt.img" |
匹配结果:true | "%Stuff%.txt" | "Stuff.txt" |
匹配结果:true | "%Stuff%.txt" | "MagicStuff.txt" |
匹配结果:false | "%Stuff%.txt" | "MagicStuff.txt.img" |
匹配结果:false | "%Stuff%.txt" | "Stuff.txt.img" |
匹配结果:false | "%Stuff%.txt" | "MagicStuff001.txt.img" |
匹配结果:true | "%Stuff%.txt" | "MagicStuff001.txt" |
匹配结果:true | "Stuff%.txt%" | "Stuff.txt" |
匹配结果:false | "Stuff%.txt%" | "MagicStuff.txt" |
匹配结果:false | "Stuff%.txt%" | "MagicStuff.txt.img" |
匹配结果:true | "Stuff%.txt%" | "Stuff.txt.img" |
匹配结果:false | "Stuff%.txt%" | "MagicStuff001.txt.img" |
匹配结果:false | "Stuff%.txt%" | "MagicStuff001.txt" |
匹配结果:true | "%Stuff%.txt%" | "Stuff.txt" |
匹配结果:true | "%Stuff%.txt%" | "MagicStuff.txt" |
匹配结果:true | "%Stuff%.txt%" | "MagicStuff.txt.img" |
匹配结果:true | "%Stuff%.txt%" | "Stuff.txt.img" |
匹配结果:true | "%Stuff%.txt%" | "MagicStuff001.txt.img" |
匹配结果:true | "%Stuff%.txt%" | "MagicStuff001.txt" |
匹配结果:true | "?Stuff?.txt?" | "1Stuff3.txt4" |
匹配结果:false | "?Stuff?.txt?" | "1Stuff.txt4" |
匹配结果:false | "?Stuff?.txt?" | "1Stuff3.txt" |
匹配结果:false | "?Stuff?.txt?" | "Stuff3.txt4" |
// *Controller 代表匹配 只要是Controller结尾的类都能匹配// Get* 代表上面匹配成功的类下 所以是Get打头的方法都能匹配[Pointcut(ClassName = "*Controller",MethodName = "Get*")]public class LoggerPointCut{}
定义好了一个Pointcut切面后 需要定义这个切面的拦截方法
配合Pointcut切面标签,可以在打了这个标签的class下定义拦截方法, 在方法上得打上特定的标签,有如下几种:
切面执行方法上打标签种类 | 说明 |
---|---|
Before标签 | 在匹配成功的类的方法执行前执行 |
After标签 | 在匹配成功的类的方法执行后执行 |
Around标签 | 承接了 匹配成功的类的方法的执行权(如果一个切面配置了Around又配置了Before或者After,那么会只执行Around) |
以上3种标签有一个可选的参数:Name (默认为空,可以和Pointcut的Name进行mapping)
因为一个class上可以打多个Pointcut切面,一个Pointcut切面可以根据name去匹配对应拦截方法
// *Controller 代表匹配 只要是Controller结尾的类都能匹配// Get* 代表上面匹配成功的类下 所以是Get打头的方法都能匹配[Pointcut(ClassName = "*Controller",MethodName = "Get*")]public class LoggerPointCut{/// <summary>/// 打上Before标签 代表满足匹配的方法 在执行之前会执行下面的Before()方法/// </summary>[Before]public void Befor(){Console.WriteLine("before");}/// <summary>/// 打上After标签 代表满足匹配的方法 在执行之前会执行下面的After()方法/// </summary>[After]public void After(){Console.WriteLine("after");}}
如果是用Around环绕的话
// *Controller 代表匹配 只要是Controller结尾的类都能匹配// Get* 代表上面匹配成功的类下 所以是Get打头的方法都能匹配[Pointcut(ClassName = "*Controller",MethodName = "Get*")]public class LoggerPointCut{/// <summary>/// 打上Around标签 承接了 匹配成功的类的方法的执行权/// </summary>/// <param name="context"></param>[Around]public void Around(AspectContext context){//执行原目标方法前Console.WriteLine(context.InvocationContext.MethodInvocationTarget.Name + "-->Start");//执行原目标方法context.InvocationProceedInfo.Invoke();//执行原目标方法后Console.WriteLine(context.InvocationContext.MethodInvocationTarget.Name + "-->End");}}
执行方法的参数说明:
执行方法的参数可以是DI容器的类型,会在执行时自动注入进来,可以使用Autowired,Value等标签来修饰参数。
还有一个特殊的执行参数可以注入,那就是AspectContext,这个类型里面你可以获取到被拦截的方法的信息,以及执行原方法的委托。
注意:这个执行后 有2种
正常执行成功
有异常,若方法参数注入了AspectContext 那么可以通过Exception属性值获得异常内容
按照上面的配置
ProductController.GetProduct 会被匹配
UserController.GetUser 会被匹配
在执行上面这2个方法的时候会
先执行 LoggerPointCut.Before方法
再执行 LoggerPointCut.After方法
利用Autofac的这个开源扩展组件很方便的实现切面编程,总结切面编程三步骤
1.定义一个切面,编写要匹配的目标类的方法(采用sql的like方式匹配),所以一个切面可以拦截n个目标
2.定义对应的拦截方法
3.执行被匹配的方法时会执行对应的拦截方法
Autofac的切面编程实现相关推荐
- Autofac的AOP面向切面编程研究
我的理解是 把系统性的编程工作封装起来 =>我给这个取个名字叫 "Aspect",然后通过AOP技术把它切进我们的业务逻辑代码 => "业务" 这样 ...
- 切面是异步还是同步操作‘_Autofac的AOP面向切面编程研究
什么是AOP: 我的理解是 把系统性的编程工作封装起来 =>我给这个取个名字叫 "Aspect",然后通过AOP技术把它切进我们的业务逻辑代码 => "业务& ...
- AOP(面向切面编程)大概了解一下
前言 上一篇在聊MemoryCache的时候,用到了Autofac提供的拦截器进行面向切面编程,很明显能体会到其优势,既然涉及到了,那就趁热打铁,一起来探探面向切面编程. 正文 1. 概述 在软件业, ...
- AOP—面向切面编程
前言 上一篇在聊MemoryCache的时候,用到了Autofac提供的拦截器进行面向切面编程,很明显能体会到其优势,既然涉及到了,那就趁热打铁,一起来探探面向切面编程. 正文 概述 在软件业,AOP ...
- 【Spring】面向切面编程AOP
AOP基础 什么是AOP [废话解释]在软件业,AOP全称Aspect Oriented Programming 即:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AO ...
- 【spring】初识aop(面向切面编程) 使用jdk动态代理
BankServiceIImple.java 代码实现: package com.zzxtit.aop;import java.math.BigDecimal;public interface Ban ...
- java切面类整合_SpringBoot2.x【五】整合AOP切面编程
SpringBoot2.x[五]整合AOP切面编程 面向方面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP). OOP中模块化的关键单元是类,而在AOP中,模块化单元是方面. ...
- Spring 面向切面编程
AOP,也就是面向方面编程或者说面向面编程,是一种很重要的思想.在企业级系统中经常需要打印日志.事务管理这样针对某一方面的需求,但是传统的面向对象编程无法很好的满足这些需求.因此催生了面向切面编程这样 ...
- Spring核心AOP(面向切面编程)
AOP(面向切面编程) 原理 相关术语 系统日志增强 异常抛出增强 最终增强 环绕增强 使用注解实现AOP AspectJ 转载于:https://www.cnblogs.com/xhddbky/p/ ...
最新文章
- 训练数据集如何划分验证测试集?train/test(val/dev) set和交叉验证(cross validation)
- java synchronized关键字_Java:手把手教你全面学习神秘的Synchronized关键字
- 【亲身经验】如何在 6 个月内成为“微软 MVP”
- java面向对象的理解_java胜于C语言,却又静态面向对象,简单?
- 别被官方文档迷惑了!这篇文章帮你详解yarn公平调度
- 程序设计模式的有趣解释-追MM
- Oracle oradebug 命令 使用说明
- 微信小程序微商城(一):https框架搭建并实现导航功能
- 谷歌浏览器一直显示弹框登陆代理解决方法
- alienfx无法与计算机,戴尔G3无法检测到AlienFX设备怎么办
- matlab如何计算方差分析,matlab-方差分析.ppt
- css方块跳动且颜色变化,CSS3 波动的方块
- 外观模式——透过现象看本质
- EasyX 图片透明设置
- pringboot餐饮点餐系统毕业设计源码301749
- Python全量字段校验
- 使用python异步框架aiohttp从NASA抓取火星图片
- 什么是SYN Flood?
- 美国站亚马逊UL2772测试报告16 CFR PART 1512自行车安全报告办理
- java什么是局部与全局变量_Java中的局部VS全局变量
热门文章
- net MVC 重定向总结
- WinHEC(Windows硬件project产业创新峰会)将2015回归
- 【慢慢学算法】:查找第k小数
- JQuery函数在IE浏览器中测试的注意事项
- 技术总监谈好的程序员如何写代码
- minecraft服务器_如何启动自己的Minecraft服务器进行多人游戏
- pcu tps_Mac版Microsoft Office 2011重新定义您的TPS报告体验
- 如何在Android Wear上节省电池寿命
- 2018-2019-1 20165211 实验四 外设驱动程序设计
- javascript基础修炼(4)——UMD规范的代码推演