Aspect-oriented programming (AOP) is a programming paradigm that allows you to separate cross-cutting concerns from the main application logic. This separation is achieved by defining aspects, which are reusable modules that can be applied to different parts of the application. Aspects can be used to implement features such as logging, security, and transaction management, without cluttering the main application code with boilerplate code.

Terminology

  • Aspect: A module that encapsulates a cross-cutting concern.
  • Join Point: A point in the execution of the program, such as method invocation, exception handling, or variable assignment.
  • Advice: The action taken by an aspect at a particular join point.
  • Pointcut: A set of join points where the advice(s) should be applied.
  • Weaving: The process of applying aspects to the main application code.

Spring AOP

Spring AOP is a key component of the Spring Framework. Spring itself uses AOP to provide transaction management, security, logging, and other cross-cutting concerns. It allows you to define aspects using AspectJ-style syntax.

Flow

When the calling code invokes a method (e.g., foo()), the Spring AOP proxy intercepts the call and applies the advice defined in the aspect. Afterwards, the proxy forwards the call to the actual object, which executes the method. The object returns control to the proxy which applies any additional advice and returns the result to the calling code.

sequenceDiagram
    participant C as Caller
    participant P as Proxy
    participant O as Object
    C->>P: Invoke: foo()
    P->>P: Before...
    P->>O: Invoke: foo()
    O->>O: foo()
    O->>P: Return: foo()
    P->>P: After...
    P->>C: Return: foo()

Pointcut Expressions

Pointcut expressions are used to define the join points where the advice should be applied. They can be used to match method invocations, field access, exception handling, and other join points. In Spring AOP, pointcut expressions are defined using AspectJ-style syntax. It does not support all AspectJ expressions (but maybe will in the future). For now, Spring AOP supports the following pointcut designators (PCD):

  • execution: Method execution join points. This is the primary pointcut designator in Spring AOP.
  • within: Limits matching to join points within certain types (e.g. method execution within a matching class).
  • this: Limits matching to join points where the bean reference (proxy) is an instance of the given type.
  • target: Limits matching to join points where the target object (object being proxied) is an instance of the given type.
  • args: Limits matching to join points where the arguments are instances of the given types.
  • @target: Limits matching to join points where the class of the executing method has an annotation of the given type.
  • @args: Limits matching to join points where the runtime type of the actual arguments passed have annotations of the given type(s).
  • @within: Limits matching to join points within types that have the given annotation.
  • @annotation: Limits matching to join points where the method has the given annotation.
  • bean: Limits matching to join points to a particular named Spring bean or to a set of named Spring beans when using wildcards.

Pointcut expressions can be combined using logical operators: && (and), || (or), and ! (not).

Examples

  • execution(* com.example.service.*.*(..)): Matches the execution of any method in the com.example.service package.
  • execution(* com.example.service.*.get*(..)): Matches the execution of any method in the com.example.service package that starts with get.
  • within(com.example.service.*): Matches any join point within the com.example.service package.
  • @annotation(com.example.annotation.MyAnnotation): Matches any method that has the @MyAnnotation annotation.
  • args(Float,..): Matches any method that takes a Float as the first parameter.
  • @within(com.example.annotation.MyAnnotation) && args(com.example.model.MyClass): Matches any method within a type that has the @MyAnnotation annotation and only takes a MyClass as parameter.