面向切面编程(AOP)和面向对象编程(OOP)类似,也是一种编程模式。Spring AOP 是基于 AOP 编程模式的一个框架,它的使用有效减少了系统间的重复代码,达到了模块间的松耦合目的。
AOP 的全称是“Aspect Oriented Programming”,即面向切面编程,它将业务逻辑的各个部分进行隔离,使开发人员在编写业务逻辑时可以专心于核心业务,从而提高了开发效率。
AOP 采取横向抽取机制,取代了传统纵向继承体系的重复性代码,其应用主要体现在事务处理、日志管理、权限控制、异常处理等方面。
目前最流行的 AOP 框架有两个,分别为 Spring AOP 和 AspectJ。
Spring AOP 使用纯 Java 实现,不需要专门的编译过程和类加载器,在运行期间通过代理方式向目标类植入增强的代码。
AspectJ 是一个基于 Java 语言的 AOP 框架,从 Spring 2.0 开始,Spring AOP 引入了对 AspectJ 的支持。AspectJ 扩展了 Java 语言,提供了一个专门的编译器,在编译时提供横向代码的植入。
AOP思想的应用场景:
AOP切面缓存
权限认证
错误处理
调试
日志记录
性能监控
数据持久化
AOP事务
三丶AOP切面执行流程
AOP切面有点像拦截器,不过跟拦截器有点区别。
四丶代码例子
这个例子开发环境使用的是.Net Core 3.0,用的AOP框架是Autofac,通过Nuget安装Autofac.Extras.DynamicProxy组件。
功能是AOP切面缓存,把查询结果缓存到Redis里,不用每次都查询数据库。
使用步骤
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 andRoleStatus=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 andRoleStatus=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思想实际上就是想把业务和公共的处理分开,对原有的代码没有一点入侵。我觉得学习一个新技术之前,先别读那么多概念性的东西,感觉越看越糊涂,只会对学习新技术产生恐惧和抵触心理。我们可以先看看新技术它能解决什么问题,实际应用场景是什么,这对学习新技术应该是有好处的。
欢迎大家关注尚硅谷java专栏了解更多java培训技术内容!