Aspect Oriented Programming (AOP) in Spring
AOP (Aspect Oriented Programming) is a programming paradigm guiding developers in structuring programs.
OOP (Object Oriented Programming) is another paradigm.
Core Concepts
- AOP Purpose: Enhance functionality without modifying original code
- Spring Philosophy: Non-invasive programming model
Key Terminology
- Join Point: Execution point in application (method execution, exception throwing, variable access)
- In Spring AOP: Method execution
- Pointcut: Expression matching join points
- Matches single/multipel methods (e.g., all
savemethods, methods starting withget)
- Matches single/multipel methods (e.g., all
- Advice: Action taken at join points (cross-cutting concerns)
- Implemented as methods in Spring AOP
- Advisor: Class containing advice definitions
- Aspect: Module combining pointcuts and advice
Annotation-Based Implementation
Dependency Configuration
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.19</version>
</dependency>
Domain Layer
Interface:
public interface ProductRepository {
void create();
void modify();
void remove();
void query();
}
Implementation:
@Repository
public class ProductRepositoryImpl implements ProductRepository {
public void create() {
long start = System.currentTimeMillis();
for(int i = 0; i < 10000; i++) {
System.out.println("Creating product...");
}
long duration = System.currentTimeMillis() - start;
System.out.println("Execution time: " + duration + "ms");
}
// Other methods omitted for brevity
}
Aspect Definition
@Component
@Aspect
public class PerformanceMonitor {
@Pointcut("execution(* com.example.repository.ProductRepository.*d*(..))")
private void operationPointcut() {}
@Around("operationPointcut()")
public Object measurePerformance(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("=== Performance Monitoring ===");
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long end = System.currentTimeMillis();
System.out.println("Operation completed in: " + (end-start) + "ms");
return result;
}
}
Confiugration
@Configuration
@ComponentScan("com.example")
@EnableAspectJAutoProxy
public class AppConfig {}
Proxy Mechanism
- Container enitialization
- Pointcut evaluation
- Bean creation:
- No match → Create target bean
- Match → Create proxy wrapping target
- Method invocation:
- Direct call to regular beans
- Proxy delegation for enhanced beans
Components:
- Target Object: Original business logic component
- Proxy: Enhanced wrapper delegating to target
Pointcut Expressions
Standard syntax: execution([modifiers] returnType package.class.method(params) [exceptions])
Wildcards:
*: Single arbitrary character
execution(* com.example..Service.find(..))
- `..`: Multiple arbitrary characters
```java
execution(* com.example..*Service.findById(..))
+: Subtype matching
execution(* *..Service+.(..))
## Advice Types
| Type | Annotation | Execution Timing |
|------------------|------------------|-------------------------------|
| Before | `@Before` | Before method execution |
| After | `@After` | After method completion |
| Around | `@Around` | Surrounds method execution |
| After Returning | `@AfterReturning`| After successful execution |
| After Throwing | `@AfterThrowing` | After exception occurence |
**Around Advice Requirements:**
- Must accept `ProceedingJoinPoint` parameter
- Call `proceed()` to invoke original method
- Handle return values and exceptions appropriately
## Data Access in Advice
### Method Parameters
```java
@Before("pointcut()")
public void logParameters(JoinPoint joinPoint) {
Object[] params = joinPoint.getArgs();
System.out.println("Parameters: " + Arrays.toString(params));
}
Return Values
@AfterReturning(pointcut="pointcut()", returning="result")
public void logResult(Object result) {
System.out.println("Method returned: " + result);
}
Exceptions
@AfterThrowing(pointcut="pointcut()", throwing="error")
public void handleException(Exception error) {
System.err.println("Error occurred: " + error.getMessage());
}
Practical Example: Input Sanitization
@Around("serviceLayer()")
public Object sanitizeInputs(ProceedingJoinPoint joinPoint) throws Throwable {
Object[] args = joinPoint.getArgs();
for(int i = 0; i < args.length; i++) {
if(args[i] instanceof String) {
args[i] = ((String)args[i]).trim();
}
}
return joinPoint.proceed(args);
}
Tags
["Spring", "AOP", "Java", "Aspect Oriented Programming", "Annotations", "Proxy Pattern"]