面向切面编程(AOP)初探

开发 开发工具
面向切面编程(AOP)是一项新的技术,它将交叉业务分离出来,作为独立单元——切面——处理。切面即是交叉业务的模块化实现,它封装了对各个类都有影响的行为,作为新的可重用的模块。

面向对象编程通过设计和语言本身提供的模块化、封装、继承、多态来实现软件复用。尽管OOP在建模以及实现复杂软件方面非常成功,它仍然有一些问题。面向切面编程(AOP)被认为是一项有前途的新技术,它通过对交叉业务的分隔来实现,而这在面向对象编程里很难做到。本文通过一个新的范例介绍AOP的基本概念。

面向对象编程 Object Oriented Programming

今天,面向对象编程已经成为主流的编程模式,在这里,现实问题被分解为一个个的包含数据和行为的对象。

在大型工程实践中,程序员发现在模块中越来越难以分离交叉业务,他们的代码也变得更加难维护。对程序设计的一丝改动都会引发大量不相关模块的改动。

交叉业务 Crosscutting Concerns

一个交叉业务的例子是“日志”,日志在分布式系统中经常被用来记录方法调用,以辅助调试。假设我们在每个函数开始前和结束后都写日志,这会使我们对所有包含方法的类做“横切”(crosscutting)。其他典型的交叉业务包括:上下文敏感的错误处理,性能优化,以及设计模式。

交叉业务可能出现在某些程序中,尤其是那些大型程序中。然而另一方面,对系统的重新设计可以将交叉业务转换成对象。AOP假定交叉业务会出现在程序中,并无法从重构中被剔除出去。

面向切面编程 Aspect Oriented Programming

面向切面的编程AOP是一项新的技术,它将交叉业务分离出来,作为独立单元——切面——处理。切面即是交叉业务的模块化实现,它封装了对各个类都有影响的行为,作为新的可重用的模块。利用AOP,我们可以用OO编程语言(如Java)开始项目,然后我们单独使用切面处理交叉业务。最后,代码和切面一起通过编织器(aspect weaver)组织成最终可执行文件。图1说明了"编织器"工作过程。注意,原始的代码不需要知道切面的任何功能;只要除去切面代码并重新编译,就能得到初始代码的功能。

AOP是一种编程概念,因此它并未绑定到任何特定的语言。事实上,它对所有单独的、垂直分解式(译注:AOP通常被认为是横向分解)的语言(不仅是OO语言)都有帮助。AOP在不同语言都有实现(如 C++, Smalltalk, C#, C, Java).

当然,受益最大的还是Java语言。下面是一些支持Java AOP的工具:

◆AspectJ

◆AspectWerkz

◆Hyper/J

◆JAC

◆JMangler

◆MixJuice

◆PROSE

◆ArchJava

由Xerox PARC所创建的AspectJ被认为是Java语言在AOP方面的一个扩展,是专门为面向切面的编程而生的。本文下面部分主要涉及AspectJ.#p#

连接点,切入点,通知和引入 Join points, Pointcut, Advice, and Introduction

就如OOP的概念包含继承、封装、多态一样,组成AOP的概念是连接点,切入点,通知和引入(Join points, Pointcut, Advice, and Introduction)。为更好的理解这些术语,我们看一下下面的例子。

  1. public class TestClass {  
  2.   public void sayHello () {  
  3.     System.out.println ("Hello, AOP");  
  4.   }  
  5.  
  6.   public void sayAnyThing (String s) {  
  7.     System.out.println (s);  
  8.   }  
  9.  
  10.   public static void main (String[] args) {    sayHello ();  
  11.     sayAnyThing ("ok");  
  12.   }  
  13. }  

我们的Java代码保存在TestClass.java,假设我们想用切面做如下修改:

在对TestClass.sayHello()方法调用之前和之后,都打印一行信息;检查TestClass.sayAnyThing() 方法的参数,至少3个字符才能执行

下面就是AspectJ 的实现。

  1. public aspect MyAspect {  
  2.    public pointcut sayMethodCall (): call (public void 
  3.                                              TestClass.say*() );  
  4.    public pointcut sayMethodCallArg (String str): call  
  5.                      (public void TestClass.sayAnyThing (String))  
  6.                      && args(str);  
  7.  
  8.    before(): sayMethodCall() {  
  9.    System.out.println("\n TestClass." +  
  10.        thisJoinPointStaticPart.getSignature().getName() +  
  11.        "start..." );  
  12.    }  
  13.  
  14.    after(): sayMethodCall() {  
  15.    System.out.println("\n TestClass." +  
  16.        thisJoinPointStaticPart.getSignature().getName() +  
  17.        " end...");  
  18.    }  
  19.  
  20.    before(String str): sayMethodCallArg(str) {  
  21.      if (str .length() < 3) {  
  22.      System.out.println ("Error: I can't say words less than 3 
  23.                              characters");  
  24.      return;  
  25.      }  
  26.    }  
  27.  } 

Line 1 定义了一个aspect,就像我们定义Java 类。跟任何Java类一样,aspect也可以拥有成员变量和方法,另外它还可以包含切入点(pointcuts),通知(advices)和引入(introductions).

Lines 2和Line 3指定我们的修改在TestClass什么地方起作用。按AspectJ术语,我们定义了2个切入点(pointcuts)。为了弄清楚切入点(pointcut)是什么意思,我们需要先定义连接点(join points).

连接点(join points)表示在程序执行过程中预先定义的“点”,AspectJ 中典型的连接点包括:方法或构造器的调用,方法或构造器的执行,字段的读取,异常处理,以及静态或动态的初始化。本文例子中,我们定义了2处连接点:对TestClass.sayHello方法的调用及对TestClass.sayAnyThing方法的调用。

切入点(Pointcut)是符合预定义规范的连接点(a set of join points)的集合,这是一个语言上的构造概念。 规范可以是明确的的函数名,也可以是包含通配符的函数名。

public pointcut sayMethodCall (): call (public void
                                        TestClass.say*() );

上面一行,我们定义了一个切入点(pointcut),叫做 sayMethodCall,它会检查所有对TestClass.sayHello方法的调用。另外,它同样会检查TestClass 类里所有以"say"开头,参数为空的公共方法(举个例子:TestClass.sayBye).

切入点(Pointcuts)用来定义“通知” (advice). AspectJ 的advice用来定义在连接点执行之前、之中、之后的额外代码。在我们的例子中,line 4-6 和line7-9 分别定义了对第一个切入点执行之前和之后的通知。Lines10-15定义了对第二个切入点的通知,即设置TestClass.sayAnyThing 方法执行的一个前置条件。

切入点pointcuts和通知advice能让你影响程序的动态执行部分,与此不同,引入(introduction)允许切面修改程序中静态的部分。通过引入(introduction), 切面可以为类添加新的方法及变量,声明类实现的接口,或将捕获的异常转为未捕获的异常。 Introduction和一个更为实用的AOP的例子是我未来一篇文章的主题。

AspectJ 编译器

回到开头,你需要从AspectJ 的官方网站上下载它的最新版本并安装它(免费的),编译和运行我们的例子非常简单:

ajc MyAspect.aj TestClass.java
java TestClass

值得注意的是,Java源代码TestClass.java 没有任何改动。你只要使用Java编译器重新编译它就能得到最初的原始程序功能。

 

【编辑推荐】

  1. 主流编程语言的选择和学习杂谈
  2. 新型动态编程语言Snow简介
  3. 程序员如何选择入门编程语言?
  4. Scala简介:面向对象和函数式编程的组合
  5. 全面介绍C#面向对象编程
责任编辑:佚名 来源: 译言
相关推荐

2012-02-10 10:32:33

JavaSpring

2013-09-17 10:37:03

AOPAOP教程理解AOP

2023-11-07 16:00:25

面向切面编程开发

2023-10-20 09:32:25

Java技术

2011-04-26 09:33:04

SpringAOP

2024-05-21 09:55:43

AspectOrientedAOP

2023-11-30 08:00:54

面向对象面向切面

2024-04-10 08:59:39

SpringAOP业务

2010-04-26 08:53:06

面向方面编程.NET

2009-06-22 11:27:59

反向控制原理面向切面编程Spring

2009-06-22 15:10:00

java 编程AOP

2021-10-27 07:15:37

SpringAOP编程(

2024-06-11 00:04:00

对象AdvisorAdvice

2013-09-09 09:41:34

2021-07-14 14:27:01

AndroidAOPhugo

2015-09-07 09:13:31

ios教学

2015-10-09 13:54:14

切面编程错误处理机制

2013-07-30 09:42:41

实现编程接口编程对象编程

2019-11-29 16:21:22

Spring框架集成

2021-06-30 00:19:43

AOP动态代理
点赞
收藏

51CTO技术栈公众号