Programación Orientada a Aspectos: Interceptando LLamadas con GroovyInterceptable

Introducción a la Programación Orientada a Aspectos

In computing, aspect-oriented programming (AOP) is a programming paradigm in which secondary or supporting functions are isolated from the main program's business logic. It aims to increase modularity by allowing the separation of cross-cutting concerns, forming a basis for aspect-oriented software development.

AOP includes programming techniques and tools that support the modularization of concerns at the level of the source code, while aspect-oriented software development refers to a whole engineering discipline.

Aspect-oriented programming entails breaking down a program into distinct parts (so-called concerns, cohesive areas of functionality). All programming paradigms support some level of grouping and encapsulation of concerns into separate, independent entities by providing abstractions (e.g. procedures, modules, classes, methods) that can be used for implementing, abstracting and composing these concerns. But some concerns defy these forms of implementation and are called crosscutting concerns because they "cut across" multiple abstractions in a program.

Ejemplo

Assume that for whatever reason we want to know the time before and after each call to a method in a class called SimplePOGO. To accomplish this task in Groovy, we simply implement the GroovyInterceptable interface and the invokeMethod() like this:

generaciondecodigos@nereida:~/Lgroovy/objects$ cat -n AOP1.groovy
 1  class SimplePOGO implements GroovyInterceptable {
 2      void simpleMethod1(){
 3          System.out.println("simpleMethod1() called")
 4      }
 5
 6      void simpleMethod2(String param1, Integer param2){
 7          System.out.println("simpleMethod2(${param1},${param2}) called")
 8          System.out.println("sleeping...")
 9          Timer.sleep(2000)
10      }
11
12      def invokeMethod(String name, args){
13          System.out.println("time before ${name} called: ${new Date()}")
14
15          //Get the method that was originally called.
16          def calledMethod = SimplePOGO.metaClass.getMetaMethod(name, args)
17
18          //The "?" operator first checks to see that the "calledMethod" is not
19          //null (i.e. it exists).
20          calledMethod?.invoke(this, args)
21
22          System.out.println("time after ${name} called: ${new Date()}\n")
23      }
24  }
25
26  simplePogo = new SimplePOGO()
27  simplePogo.simpleMethod1()
28  simplePogo.simpleMethod2("stringParam", 24)
29  simplePogo.simpleMethod3(1, 2, 4)

Ejecución

generaciondecodigos@nereida:~/Lgroovy/objects$ groovy AOP1.groovy
time before simpleMethod1 called: Tue Feb 23 16:18:11 WET 2010
simpleMethod1() called
time after simpleMethod1 called: Tue Feb 23 16:18:11 WET 2010

time before simpleMethod2 called: Tue Feb 23 16:18:11 WET 2010
simpleMethod2(stringParam,24) called
sleeping...
time after simpleMethod2 called: Tue Feb 23 16:18:13 WET 2010

time before simpleMethod3 called: Tue Feb 23 16:18:13 WET 2010
time after simpleMethod3 called: Tue Feb 23 16:18:13 WET 2010

Inconvenientes

Esta técnica es adecuada siempre que no se de una de estas circunstancias:

Véase también



Subsecciones
Casiano Rodríguez León
2010-04-30