Spring.NET学习笔记12——面向切面编程(基础篇)
AOP即面向切面编程(Aspect Oriented Programming的缩写),是OOP(面向对象编程)的一种延续形式。是通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术,它从一个不同于OOP的角度来看待程序的结构:OOP将应用程序分解为一系列表现为继承关系的对象;AOP 则把程序分解为一系列方面(aspects)或者关注点(concerns)。AOP将诸如事务管理等本来横向分布在多个对象中的关注点进行了模块化处理(这些关注点也常称为横切(crosscutting)关注点)。在Spring.NET中提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。
下面我举个例子来说明这一切:
场景:业务类CompanyManager在调用Save方法的时候需要调用SecurityManager类判断权限是否足够(图1)。
附件: 2009-11-12.1.gif
图1
准备条件:
- public class CompanyDao
- {
- public void Save()
- {
- Console.WriteLine("保存数据");
- }
- }
- public interface ICompanyManager
- {
- string UserName { get; set; }
- void Save();
- }
- public interface ISecurityManager
- {
- bool IsPass(string userName);
- }
SecurityManager
- public class SecurityManager : ISecurityManager
- {
- /**//// <summary>
- /// 判断权限
- /// </summary>
- /// <param name="userName"></param>
- /// <returns></returns>
- public bool IsPass(string userName)
- {
- return userName == "admin";
- }
- }
第一种实现方式,我们通常会这样做:直接在CompanyManager类中调用ISecurityManager接口的IsPass方法判断权限。
SimpleCompanyManager
- public class SimpleCompanyManager : ICompanyManager
- {
- 可通过外部注入的属性#region 可通过外部注入的属性
- public string UserName { get; set; }
- public CompanyDao Dao { get; set; }
- #endregion
- public void Save()
- {
- //判断权限
- ISecurityManager security = new SecurityManager();
- if (security.IsPass(UserName))
- {
- //执行业务方法
- //.
- //调用DAO层方法
- Dao.Save();
- }
- else
- {
- //执行其它业务方法
- Console.WriteLine("您没有该权限");
- }
- }
- }
这样CompanyManager类与ISecurityManager或SecurityManager会发生业务性耦合。聪明的朋友会发现在GOF(设计模式)中有一种模式(代理模式)可以解除这种耦合。
第二种实现方式,代理模式(Proxy Pattern):什么是代理模式?是给某一个对象提供一个代理对象,并由代理对象控制对源对象的引用。代理就是一个人或一个机构代表另一个人或者一个机构采取行动。某些情况下,客户不想或者不能够直接引用一个对象,代理对象可以在客户和目标对象直接起到中介的作用。客户端分辨不出代理主题对象与真实主题对象。代理模式可以并不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,这时候代理对象不能够创建被代理对象,被代理对象必须有系统的其他角色代为创建并传入(图2)。
附件: 2009-11-12.3.gif
图2
CompanyManager
- public class CompanyManager : ICompanyManager
- {
- 可通过外部注入的属性#region 可通过外部注入的属性
- public string UserName { get; set; }
- public CompanyDao Dao { get; set; }
- #endregion
- public void Save()
- {
- //执行业务方法
- //.
- //调用DAO层方法
- Dao.Save();
- }
- }
CompanyProxyManager
- public class CompanyProxyManager : ICompanyManager
- {
- public string UserName { get; set; }
- private ICompanyManager target = new CompanyManager();
- public void Save()
- {
- //判断权限
- ISecurityManager security = new SecurityManager();
- if (security.IsPass(UserName))
- {
- //调用目标对象Save方法
- target.Save();
- }
- else
- {
- Console.WriteLine("您没有该权限");
- }
- }
- }
这样,CompanyManager类就不必与判断权限的类SecurityManager耦合,但是这种方式实现起来比较麻烦。
第三种实现方式,Spring.NET提供的AOP:AopAlliance.Intercept.IMethodInterceptor接口和ProxyFactory类的组合。
AroundAdvice
- public class AroundAdvice : IMethodInterceptor
- {
- //权限系统类(可外部注入)
- private ISecurityManager manager = new Service.SecurityManager();
- public object Invoke(IMethodInvocation invocation)
- {
- //拦截Save方法
- if (invocation.Method.Name == "Save")
- {
- ICompanyManager target = (ICompanyManager)invocation.Target;
- return manager.IsPass(target.UserName) ? invocation.Proceed() : null;
- }
- else
- {
- return invocation.Proceed();
- }
- }
- }
Program
- class Program
- {
- static void Main(string[] args)
- {
- ICompanyManager target = new CompanyManager() { Dao = new CompanyDao(), UserName = "admin" };
- ProxyFactory factory = new ProxyFactory(target);
- factory.AddAdvice(new AroundAdvice());
- ICompanyManager manager = (ICompanyManager)factory.GetProxy();
- manager.Save();
- Console.ReadLine();
- }
- }
输出:保存数据
Spring.NET利用System.Reflection.Emit命名空间下的类在运行时动态创建IL代码来生成AOP代理。这使得代理(的创建)非常高效,并且不受任何继承层次的限制。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
2008-03-26 c# 二分查找
2008-03-26 几种字符串反转方法效率比较
2008-03-26 C#反转字符串效率最高的方法