Appearance
切面编程
Aspect Oriented Programming简称AOP,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
切面常用于以下场景
- 鉴权
- 数据校验
- 异常处理
- 内容分发
- 数据缓存
- 日志跟踪
- 性能优化
- 异步持久化
- 事务
在AsDI中,切面编程是非侵入式的,在代码中任意位置定义切面都皆可,定义好以后,自动生效,用户的服务不需要作任何改动。
如下,定义一个切面
C#
[Fit("1")]
public class LogInterceptor : IInterceptor
{
public object Around(AspectEntity aspect)
{
var start = DateTime.Now;
Console.WriteLine("开始执行:" + aspect.Method.TypeName + "." + aspect.Method.Name+"()");
var rtn = aspect.Continue();
Console.WriteLine("结束执行:" + aspect.Method.TypeName + "." + aspect.Method.Name + "(),执行结果:" + rtn + ",用时:" + (DateTime.Now - start).TotalMilliseconds + "ms");
return rtn;
}
}如果有以下业务逻辑
C#
public interface IUserController
{
public void Print();
}
[Service]
public class UserController : IUserController
{
[AutoAssemble]
private IUserService user;
public void Print()
{
Console.WriteLine("Hello " + user.GetUserName());
}
}
public interface IUserService
{
string GetUserName();
}
[Service]
public class UserService1 : IUserService
{
public string GetUserName()
{
Console.WriteLine("正在执行IUserService.GetUserName()...");
return "Jack";
}
}此时,调用IUserController的Print方法时,会输出:
sh
> 开始执行:IUserController.Print()
> 开始执行:IUserService.GetUserName()
> 正在执行IUserService.GetUserName()...
> 结束执行:IUserService.GetUserName(),执行结果:Jack,用时:0.3962ms
> Hello Jack
> 结束执行:IUserController.Print(),执行结果:,用时:3.9799ms如果将 [Fit("1")] 改一下,如下:
C#
[Fit("name('.*Service.*')")]
public class LogInterceptor : IInterceptor此时,调用IUserController的Print方法时,会输出:
sh
> 开始执行:IUserService.GetUserName()
> 正在执行IUserService.GetUserName()...
> 结束执行:IUserService.GetUserName(),执行结果:Jack,用时:0.3962ms
> Hello Jack也就是说,LogInterceptor 不再对 IUserController 生效
注意
- 自定义切面,必须继承自 IInterceptor
- 必须要带上 [Fit] 标注,以规定生效范围
- 在Around方法中,如果不执行 aspect.Continue() ,业务逻辑将不再被执行,请务必当心
- 非抽象的方法由于无法代理,所以无法切面,即无法直接对非抽象类、结构体、枚举等类型切面,这也是我们推荐面向接口编程的原因之一