AOP

A programming paradigm that enables the management of common functionalities (cross-cutting concerns) separate from the core business logic, by modularizing them into an “Aspect.”

  • Core concept here is Separation of Concerns
  • Applying AOP allows defining common functionalities in one place, automatically “woven” into the necessary core logic
  • Limitations of OOP
    • OOP separates responsibilities by roles (classes/modules).
    • Repetitive logic like logging, security, transactions, and timing often appears across modules. This logic gets scattered and duplicated.
    • OOP struggles to eliminate such cross-cutting concerns cleanly.
  • Cross-Cutting Concerns
    • functionalities that are not directly related to business logic but appear repetitively across multiple layers or components
    • AOP reduces this
    • Examples
      • Transaction (very good w/ AOP)
      • Logging
      • Security
      • Checking performance

Example

Before AOP

@Service
public class MemberService {
 
    private final MemberRepository memberRepository;
 
    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
 
    public void join(Member member) {
        long start = System.currentTimeMillis(); // Non-core logic
 
        try {
            // Core Logic
            memberRepository.save(member);
        } finally {
            long end = System.currentTimeMillis(); // Non-core logic
            long time = end - start;
            System.out.println("MemberService.join execution time = " + time + "ms"); // Non-core logic
        }
    }
}
  • Core logic and supplementary logic are mixed within a single source code file.
  • The join() method contains execution time measurement code mixed with its core logic (saving a member).
  • If this logic is repeated across multiple methods or classes, it increases duplication, making maintenance difficult.

After AOP

// Core Logic Class
@Service
public class MemberService {
 
    private final MemberRepository memberRepository;
 
    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
 
    public void join(Member member) {
        memberRepository.save(member); // Pure core logic
    }
}
 
// Common functionality (here, logging execution time) separated
@Aspect // Marks this class as an Aspect
@Component // Registers this Aspect as a Spring Component/Bean
public class TimeTraceAspect {
 
    // Specifies where this advice should be applied (all methods in 'com.example' and its sub-packages)
    @Around("execution(* com.example..*(..))")
    public Object trace(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis(); // Common functionality
 
        try {
            return joinPoint.proceed(); // Executes the actual target method
        } finally {
            long end = System.currentTimeMillis(); // Common functionality
            long time = end - start;
            System.out.println("[Execution Time] " + joinPoint.getSignature() + " = " + time + "ms"); // Common functionality
        }
    }
}
  • Core logic and supplementary logic can be completely separated.
  • Common functionalities are managed in one place, greatly improving maintainability and extensibility.

AOP in Spring

Summary

Spring supports @AspectJ style AOP and primarily provides proxy-based AOP from the full AspectJ capabilities.

  • Proxy-based AOP implementation: It creates and provides a proxy for the target object. This proxy, which wraps the target, is generated at server runtime.
  • Provides only method join points: Supplementary functionalities (advice) can only be applied at runtime when the core functionality’s (target object’s) method is called.

Key Components

TermDescription
Aspect- A module where common functionality is defined.
- A cross-cutting concern performed separately from the core logic.
- E.g., logging, transactions.
Join Point- Actual place in your code where the Advice could be applied
- e.g., the exact moment memberService.join() is called
Advice- The specific code for the extra action (e.g., long start = ...; try { ... } finally { ... }).
- Also says when to do it (e.g., @Around the method).
- E.g., @Before, @After, @Around, @AfterReturning, @AfterThrowing.
PointcutThis is a rule that defines where your Advice should run (e.g., “any method call in com.example package”).
- A selection of Join Points where Advice has the potential to be applied (a candidate set).
- Primarily selected using expressions. (like a filter)
WeavingThe process of applying an Advice to the core business logic.