什么是面向切面编程AOP

9次阅读

共计 3013 个字符,预计需要花费 8 分钟才能阅读完成。

←←←←←←←←←←←← 快!点关注
一、前言
看过一些描述关于 AOP 切面编程的文章,写的太概念化让人很难理解,下面是我自己的理解,希望能帮到新人,如有错误欢迎指正。
二、AOP 是什么,它的应用场景是什么?
AOP 也跟 IOC,OOP 这些思想一样它只是一种编程思想。Autofac、Spring.Net、Castle 这些组件实现了 AOP 切面编程思想的框架。AOP 说白了就是在运行时,动态的将代码切入到类的指定方法的指定位置上,这种思想就是面向切面的编程思想。
如果你发现你的方法中有很多重复的代码就可以考虑用 aop 来精简代码了。比如说你想监控每个方法的耗时,按照传统的方法是每个方法都加上监控代码,如果用 AOP 思想去解决问题,就可以把跟监控代码放到方法的外面去写。
AOP 思想的应用场景:

AOP 切面缓存
权限认证
错误处理
调试
日志记录
性能监控
数据持久化
AOP 事务

三、AOP 切面执行流程
AOP 切面有点像拦截器,不过跟拦截器有点区别。

四、代码例子
这个例子开发环境使用的是.Net Core 3.0,用的 AOP 框架是 Autofac,通过 Nuget 安装 Autofac.Extras.DynamicProxy 组件。
使用步骤
1.Startup 中把 BlogCacheAOP 切面 切入到 Titan.Blog.AppService.dll 下所有接口实现里。
var servicesDllFile = Path.Combine(basePath, “Titan.Blog.AppService.dll”);// 获取项目绝对路径
var assemblysServices = Assembly.LoadFile(servicesDllFile);
builder.RegisterAssemblyTypes(assemblysServices)
.AsImplementedInterfaces()
.InstancePerLifetimeScope()
.EnableInterfaceInterceptors()
.InterceptedBy(typeof(BlogCacheAOP));//AOP 切面缓存
2. 切面公共代码

3. 给方法标记特性,只有指定特性的方法才会执行公共代码
/// <summary>
/// 获取系统中所有的权限
/// </summary>
/// <returns></returns>
[Caching(AbsoluteExpiration = 10)]
public async Task<List<SysRoleModuleButtonDto>> GeRoleModule()
{
var dto = await _iSysRoleModuleButtonRepository.QueryAsNoTracking(x => x.ModuleType == 0);//
var roleModuleButton = dto.MapToList<SysRoleModuleButton, SysRoleModuleButtonDto>();
if (roleModuleButton.Count > 0)
{
foreach (var item in roleModuleButton)
{
item.SysRole = _iSysRoleRepository.QueryBySql($”select * from SysRole where SysRoleId='{item.SysRoleId}’ and IsDelete!=1 and RoleStatus=1″).Result.FirstOrDefault();
item.SysModule = _iSysModuleRepository.QueryBySql($”select * from SysModule where SysModuleId='{item.SysModuleId}’ and ModuleStatus=1 and IsDelete!=1″).Result.FirstOrDefault();
}

}
return roleModuleButton;
}
这个是 AOP 切面缓存,它的功能是将包含 CachingAttribute 特性的方法的返回值缓存到 Redis 里,下次在访问这个方法,会先去缓存中查询如果有则直接跳过这个方法,直接从 Redis 里获取之前缓存的结果集,如果没有则会执行方法获取返回值在缓存到 Redis 里。
以此,我们可以开发其他类似功能,比如性能监控,日志监控,AOP 事务,是不是很强大。具体代码执行流程请下载这个项目(下面有 github 地址),自己调试下上面的例子就明白了。
还有一个要注意的,我这个项目控制器和服务实现解耦了,如果没有解耦的话,控制器直接调服务的话,AOP 注册方式和服务要做修改。
1.Startup 中 AOP 注册代码
//// 标记了虚方法 virtual 的才会进入切面
var assemblysModels = Assembly.Load(“Titan.Blog.AppService”);
builder.RegisterAssemblyTypes(assemblysModels)
.EnableClassInterceptors()
.InterceptedBy(typeof(BlogCacheAOP));
2. 方法要加上 virtual,否则进不了切面
/// <summary>
/// 获取系统中所有的权限
/// </summary>
/// <returns></returns>
[Caching(AbsoluteExpiration = 10)]
public virtual async Task<List<SysRoleModuleButtonDto>> GeRoleModule()
{
var dto = await _iSysRoleModuleButtonRepository.QueryAsNoTracking(x => x.ModuleType == 0);//
var roleModuleButton = dto.MapToList<SysRoleModuleButton, SysRoleModuleButtonDto>();
if (roleModuleButton.Count > 0)
{
foreach (var item in roleModuleButton)
{
item.SysRole = _iSysRoleRepository.QueryBySql($”select * from SysRole where SysRoleId='{item.SysRoleId}’ and IsDelete!=1 and RoleStatus=1″).Result.FirstOrDefault();
item.SysModule = _iSysModuleRepository.QueryBySql($”select * from SysModule where SysModuleId='{item.SysModuleId}’ and ModuleStatus=1 and IsDelete!=1″).Result.FirstOrDefault();
}

}
return roleModuleButton;
}
3. 切面代码不需要改动
五、结语
AOP 思想实际上就是想把业务和公共的处理分开,对原有的代码没有一点入侵。我觉得学习一个新技术之前,先别读那么多概念性的东西,感觉越看越糊涂,只会对学习新技术产生恐惧和抵触心理。我们可以先看看新技术它能解决什么问题,应用场景是什么,这对学习新技术应该是有好处的。

正文完
 0