如果要做为一名合格的软件架构师,AOP是必须知道的一门技术。那么AOP是什么呢,这就是今天所讨论的内容(也是本人最近一阵子的学习总结,希望大家多多指点)。
AOP,全称Aspect Oriented Programming,中文名称叫面向方面编程,也叫面向切面编程。
在实际项目开发过程中,我们往往会注意到有一些模块/功能,如权限,缓存等,需要存在于软件的各个业务模块中,而这些模块/功能又与业务模块没有任何关系,甚至在设计业务模块时我们完全不用考虑这些模块/功能的存在,但是在开发过程中才发现这些模块/功能会给我们带来无尽的烦恼。因为传统的OOP方法考虑问题的出发点往往是要解决问题的本身和延伸,所以遇到此类情况时传统的OOP方法就很难解决。然而对业务模块和此类模块稍作分析,我们就会发现,其实它们本质是相同的,只是解决的问题不同,对一个软件的关注点不同,如下图所示:
结合自己的经验,由图可知,日志,安全,事务等一类的模块在一个软件项目中的位置,AOP要解决的就是此类问题。 AOP的目标便是对这些“横切关注点”和业务模块解耦,从而提升软件的稳定性,扩展性。
AOP通常包含以下主要概念:
- 方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中横切关注点中一个很好的例子。
- 连接点(Joinpoint):程序执行过程中明确的点,如方法的调 用或特定的异常被抛出。
- 通知(Advice):在特定的连接点AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。
- 切入点(Pointcut):指定一个通知将被引发的一系列连接点 的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。
- 引入(Introduction):添加方法或字段到通知化类。
- 接口(IsModified),来简化缓存。
- 目标对象(Target object):包含连接点的对象。也被用来 引用通知化或代理化对象。
- AOP代理: AOP框架创建的对象,包含通知。
- 织入(Weaving):组装方面创建通知化对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他一些纯Java AOP框架, 使用运行时织入。
AOP通知类型包括:
- Around通知: 包围一个连接点的通知,如方法调用。这是最强大的通知。Aroud通知在方法调用前后完成自定义的行为。它们负责选择继续执行连接点或直接返回它们自己的返回值或抛出异常来短路执行。
- Before通知: 在一个连接点之前执行的通知,但这个通知 不能阻止流程继续执行到连接点(除非它抛出一个异常)。
- Throws通知: 在方法抛出异常时执行的通知。
- After returning通知: 在连接点正常完成后执行的通知, 例如,如果一个方法正常返回,没有抛出异常。
- Around通知是最通用的通知类型。大部分基于拦截器的AOP框架如Nanning和JBoss4只提供 Around通知。
通常AOP的关注点有以下几方面:
- 权限(Authentication)
- 缓存(Cache)
- 内容传递(Context passing)
- 错误处理(Error handling)
- 懒加载(Lazy loading)
- 调试(Debug)
- 日志(Log)
- 跟踪,优化,校准(tracing, profiling and monitoring)
- 性能优化(Performance optimization)
- 持久化(Persistence)
- 资源池(Resource pooling)
- 同步(Synchronization)
- 事务(Transactions)
了解了AOP的应用场景,下面以权限为例,比较一下传统方法与AOP方法各自的实现,说明AOP技术的应用。
传统方法:
BusinessA ClassicsPermission() { if (tag == "Pass") { return new BusinessA(); } throw new Exception("你没有权限操作BusinessA."); }
这种是常见的OO做法,它带来以下一些问题:
1、业务逻辑冗余:权限校验过程并不是业务逻辑执行的一部分,这个工作是属于系统的,但是,在这种情况下,我们不得不把系统的权限校验过程和业务逻辑执行过程掺杂在一起,造成混乱。
2、代码冗余:使用这种方法,我们必须所有的业务逻辑代码中包含权限验证代码,使得同样校验的代码充斥在整个软件中,造成代码冗余。
3、紧耦合:使用这种方法,在业务或权限任何一方发生改变时都有可能影响到其他部分,造成耦合。下面所有的问题都是因此而来。
4、不易扩展:依次类推,如果要添加其他横向模块,将导致代码冗余,耦合泛滥,到最后甚至不可收拾;
5、不灵活:使用这种方法,任何一个横向变化都有可能导致代码的修改;
然而,我们利用AOP就可以很方便的解决上述问题,如下:
[PermissionValidate] class BusinessA { }
上面是AOP的实现方法,可以看到,业务与权限几乎没有关系,上面出现的冗余,耦合问题迎刃而解。
通过上面描述可知,AOP方法解决的是横向问题,那么它是如何实现的呢?答案是代理。代理对于客户,业务都是透明的,只是在其中加入的控制,而这些控制可以根据需求灵活的改变而不影响客户与业务。代理的基本原理如下图:
由图可知,AOP关注的是aProxy,它将横向业务及变化放在客户与业务的中间,而不影响二者。
综上所述,AOP是一种解决软件中横向问题(公共模块)的思想,为软件架构师解决此类问题提供了一种行之有效的方法。
注:文中部分内容为本人学习时收集整理而来。
对的就做,做的就对