什么是面向切面编程?

271

我了解面向对象编程,并且已经写了很长时间的OO程序。人们似乎谈论面向方面的编程,但我从未真正学习过它是什么以及如何使用它。基本范式是什么?

这个问题与此相关,但并没有完全问到:

面向方面编程 vs. 面向对象编程


10
在我看来,问题中提供的链接比这里被接受的答案更清晰和详尽。阅读这个问题的人可能会先看那个链接。 - David Chen
8个回答

233

AOP解决了“横切关注点”的问题,这些关注点是在不同的方法中重复出现的任何类型的代码,通常不能完全重构为自己的模块,例如日志记录或验证。因此,使用AOP可以将这些内容从主要代码中剥离,并垂直定义,如下所示:

function mainProgram()
{ 
   var x =  foo();
   doSomethingWith(x);
   return x;
}

aspect logging
{ 
    before (mainProgram is called):
    { 
       log.Write("entering mainProgram");
    }

    after (mainProgram is called):
    { 
       log.Write(  "exiting mainProgram with return value of "
                  + mainProgram.returnValue);
    }
 } 

aspect verification
{ 
    before (doSomethingWith is called):
    { 
       if (doSomethingWith.arguments[0] == null) 
       { 
          throw NullArgumentException();
       }

       if (!doSomethingWith.caller.isAuthenticated)
       { 
          throw Securityexception();
       }
    }
 }

然后使用一个方面编织器将代码编译成以下形式:

function mainProgram()
{ 
   log.Write("entering mainProgram");

   var x = foo();   

   if (x == null) throw NullArgumentException();
   if (!mainProgramIsAuthenticated()) throw Securityexception();
   doSomethingWith(x);   

   log.Write("exiting mainProgram with return value of "+ x);
   return x;
} 

18
你需要语言支持吗?你的示例是用哪种语言编写的? - Sophie
11
这是伪代码,但最著名的例子是AspectJ,它是Java的AOP修改版本,使用一种称为切点的类似技术。 - Mark Cidade
82
巫毒。我原以为面向对象编程已经够复杂了。 - Aiden Bell
19
马克,这就像装饰方法的进入和退出点吗? - Filip Dupanović
4
如果远距离不可见的操作被视为巫术,那么是的,它就是巫术。在 Moose 元编程中,像 before, after, around, inner, augment 这样的 方法修饰符 正好做到了这点。它会掩盖程序的执行流程。尤其是当它们来自该系统版本的方面(aspect)时,即所谓的角色 (roles),几乎无法追踪。使用这些工具可以组合出令人惊讶的复杂系统。 - tchrist
显示剩余12条评论

13

很不幸,使AOP在一般的中大型组织中真正有用似乎相当困难。(编辑支持、控制感、从不那么重要的事情开始导致代码腐败、人们回家与家人在一起等等。)

我将我的希望寄托在复合导向编程上,这是越来越现实的东西。它连接了许多流行的想法,并给你带来了真正酷的东西。

看看一个正在崛起的实现:qi4j.org/

附注:实际上,我认为 AOP 的优美之处也是其致命缺点:它是非侵入式的,让人们无视它,因此在大多数组织中将被视为次要问题。


12

摘自《Spring实战》

AOP通常被定义为一种在软件系统中促进关注点分离的技术。系统由多个组件组成,每个组件负责特定的功能。但是,这些组件通常还承担除其核心功能之外的其他职责。系统服务,如日志记录、事务管理和安全性,经常出现在其核心职责是其他内容的组件中。这些系统服务通常被称为横切关注点,因为它们倾向于跨越系统中的多个组件。


9

为了完整起见,以下内容翻译自重复内容(爱因斯坦):

经典的例子是安全和日志记录。不要在应用程序中编写代码来记录x的发生或检查对象z是否具有安全访问控制,而是使用一种语言机制“超出”正常代码的范围系统地注入安全或日志记录到不具有它们的例程中,即使您的代码没有提供它 - 它也被处理了。

更具体的例子是操作系统为文件提供访问控制。软件程序不需要检查访问限制,因为底层系统会为其完成这项工作。

如果您认为需要AOP,则根据我的经验,实际上您需要在系统内投入更多的时间和精力,专注于良好的结构/系统设计,并进行适当的元数据管理。


7

为了完整起见(Buzzer),以下内容是复制的:

.NET中的类和方法属性是一种面向方面编程的形式。您可以使用属性装饰您的类/方法。在幕后,这会向您的类/方法添加代码,执行属性的特定功能。例如,将类标记为可序列化允许自动对其进行序列化,以便存储或传输到另一个系统。其他属性可能会将某些属性标记为不可序列化,这些属性将自动从序列化对象中省略。序列化是一种方面,由系统中的其他代码实现,并通过“配置”属性(装饰)应用于您的类。


5
这是一个AOP的例子,以Spring AOP为例。该示例非常易于理解。
Spring AOP(面向切面编程)框架用于将横切关注点模块化为方面。简单来说,它只是一个拦截器,用于拦截某些进程,例如当执行方法时,Spring AOP可以劫持执行方法,并在方法执行前或后添加额外的功能。
参考:http://www.mkyong.com/spring/spring-aop-examples-advice/

在计算机领域,面向切面编程(AOP)是一种旨在通过允许分离横切关注点来提高模块化的编程范式。 - R.F

4

AOP是一种更好地模块化应用程序的方式,适用于跨越多个边界的功能。 AOP是另一种封装这些特性并遵循单一职责原则的方法,通过将这些横切关注点(记录日志、错误处理等)移出应用程序的主要组件。当适当使用AOP时,可以提高应用程序随时间推移的可维护性和可扩展性水平。


0
我们在面向方面编程中的目标是减少样板代码的数量。
让我们举个例子,我们有一个服务,在这个服务中,让我们先打印服务.start()日志,然后是服务事务日志,最后是标准日志。
我们的1.log过程和3.log过程在包下是相同的,所以我们可以通过将其作为横切面来减少样板代码的编写。
什么是面向方面编程?
AOP是一种帮助减少软件复杂性并增加模块化的方法。这里的模块化目的是将非功能代码,即在应用过程中在系统的许多部分中使用的交叉利益,分离成小块(横切关注点的分离)。通过这种方式,将在整个应用程序中使用的结构从系统中抽象出来并封装起来。它允许在许多地方使用。总的来说,可以说AOP有助于改进现有系统,而不是解决问题。
在这一点上,我们可以在这里执行常见操作和减少操作。
面向方面编程的好处是什么?
我们的应用程序更加灵活易管理, 摆脱了重复的代码模式, 代码更加清晰易懂, 核心逻辑和交叉点分离。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接