0
# Spring Boot Starter AOP
1
2
Spring Boot starter for aspect-oriented programming with Spring AOP and AspectJ. This starter automatically configures Spring AOP support and enables developers to implement cross-cutting concerns like logging, security, transactions, and caching through declarative programming using annotations and pointcut expressions.
3
4
## Package Information
5
6
- **Package Name**: spring-boot-starter-aop
7
- **Group ID**: org.springframework.boot
8
- **Language**: Java
9
- **Installation**:
10
```gradle
11
implementation 'org.springframework.boot:spring-boot-starter-aop:3.5.3'
12
```
13
14
For Maven:
15
```xml
16
<dependency>
17
<groupId>org.springframework.boot</groupId>
18
<artifactId>spring-boot-starter-aop</artifactId>
19
<version>3.5.3</version>
20
</dependency>
21
```
22
23
## Core Imports
24
25
```java
26
import org.aspectj.lang.annotation.Aspect;
27
import org.aspectj.lang.annotation.Before;
28
import org.aspectj.lang.annotation.After;
29
import org.aspectj.lang.annotation.AfterReturning;
30
import org.aspectj.lang.annotation.AfterThrowing;
31
import org.aspectj.lang.annotation.Around;
32
import org.aspectj.lang.annotation.Pointcut;
33
import org.aspectj.lang.JoinPoint;
34
import org.aspectj.lang.ProceedingJoinPoint;
35
import org.springframework.stereotype.Component;
36
```
37
38
## Basic Usage
39
40
```java
41
import org.aspectj.lang.JoinPoint;
42
import org.aspectj.lang.annotation.Aspect;
43
import org.aspectj.lang.annotation.Before;
44
import org.aspectj.lang.annotation.AfterReturning;
45
import org.springframework.stereotype.Component;
46
47
@Aspect
48
@Component
49
public class LoggingAspect {
50
51
@Before("execution(* com.example.service.*.*(..))")
52
public void logBefore(JoinPoint joinPoint) {
53
System.out.println("Executing: " + joinPoint.getSignature().getName());
54
}
55
56
@AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result")
57
public void logAfterReturning(JoinPoint joinPoint, Object result) {
58
System.out.println("Completed: " + joinPoint.getSignature().getName() +
59
" with result: " + result);
60
}
61
}
62
```
63
64
## Configuration Properties
65
66
The starter provides these configuration properties for customizing AOP behavior:
67
68
```properties { .api }
69
# Enable/disable AOP auto-configuration
70
# Type: Boolean
71
# Default: true (when missing, defaults to true)
72
# Description: Add @EnableAspectJAutoProxy support
73
spring.aop.auto=true
74
75
# Control proxy type for AOP proxies
76
# Type: Boolean
77
# Default: true (when missing, defaults to true)
78
# Description: Whether subclass-based (CGLIB) proxies are to be created (true),
79
# as opposed to standard Java interface-based proxies (false)
80
spring.aop.proxy-target-class=true
81
```
82
83
## Architecture
84
85
The starter enables AOP through several key components:
86
87
- **Auto-Configuration**: `AopAutoConfiguration` automatically enables `@EnableAspectJAutoProxy` when conditions are met
88
- **Proxy Creation**: Automatic proxy creation for beans matching defined pointcuts
89
- **Weaving Support**: Runtime weaving through AspectJ weaver dependency
90
- **Conditional Configuration**: Different proxy strategies based on AspectJ availability and configuration
91
92
## Capabilities
93
94
### Aspect Definition
95
96
Create aspects by combining `@Aspect` with `@Component` annotations.
97
98
```java { .api }
99
@Aspect
100
@Component
101
public class AspectName {
102
// Aspect methods with advice annotations
103
}
104
```
105
106
### Pointcut Expressions
107
108
Define join points where advice should be executed.
109
110
```java { .api }
111
@Pointcut("execution(* com.example.service.*.*(..))")
112
public void serviceLayerPointcut() {}
113
114
@Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")
115
public void transactionalMethods() {}
116
117
@Pointcut("within(com.example.controller..*)")
118
public void controllerPackage() {}
119
```
120
121
**Common Pointcut Expressions:**
122
- `execution(* package.Class.method(..))` - Method execution
123
- `within(package..*)` - Within package or subpackages
124
- `@annotation(AnnotationType)` - Methods with specific annotation
125
- `args(ArgType)` - Methods with specific argument types
126
- `target(TargetType)` - Methods on specific target types
127
128
### Before Advice
129
130
Execute advice before method execution.
131
132
```java { .api }
133
/**
134
* Executes before the target method
135
* @param joinPoint - Provides access to method signature and arguments
136
*/
137
@Before("pointcut-expression")
138
public void beforeAdvice(JoinPoint joinPoint) {
139
// Advice logic
140
}
141
```
142
143
### After Returning Advice
144
145
Execute advice after successful method completion.
146
147
```java { .api }
148
/**
149
* Executes after method returns successfully
150
* @param joinPoint - Provides access to method signature and arguments
151
* @param result - The return value (optional parameter)
152
*/
153
@AfterReturning(pointcut = "pointcut-expression", returning = "result")
154
public void afterReturningAdvice(JoinPoint joinPoint, Object result) {
155
// Advice logic
156
}
157
```
158
159
### After Throwing Advice
160
161
Execute advice after method throws an exception.
162
163
```java { .api }
164
/**
165
* Executes after method throws an exception
166
* @param joinPoint - Provides access to method signature and arguments
167
* @param exception - The thrown exception (optional parameter)
168
*/
169
@AfterThrowing(pointcut = "pointcut-expression", throwing = "exception")
170
public void afterThrowingAdvice(JoinPoint joinPoint, Exception exception) {
171
// Exception handling logic
172
}
173
```
174
175
### After (Finally) Advice
176
177
Execute advice after method completion (success or exception).
178
179
```java { .api }
180
/**
181
* Executes after method completion regardless of outcome
182
* @param joinPoint - Provides access to method signature and arguments
183
*/
184
@After("pointcut-expression")
185
public void afterAdvice(JoinPoint joinPoint) {
186
// Cleanup logic
187
}
188
```
189
190
### Around Advice
191
192
Execute advice around method execution with control over method invocation.
193
194
```java { .api }
195
/**
196
* Executes around method execution with full control
197
* @param proceedingJoinPoint - Allows proceeding with method execution
198
* @return Object - Must return the method result or alternative value
199
* @throws Throwable - Can throw exceptions
200
*/
201
@Around("pointcut-expression")
202
public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
203
// Before logic
204
Object result = proceedingJoinPoint.proceed(); // Execute target method
205
// After logic
206
return result;
207
}
208
```
209
210
## Types
211
212
### JoinPoint Interface
213
214
Provides access to join point information in advice methods.
215
216
```java { .api }
217
interface JoinPoint {
218
/** Get method signature information */
219
Signature getSignature();
220
221
/** Get method arguments */
222
Object[] getArgs();
223
224
/** Get target object instance */
225
Object getTarget();
226
227
/** Get proxy object instance */
228
Object getThis();
229
230
/** Get join point kind (METHOD_EXECUTION, etc.) */
231
String getKind();
232
233
/** Get source location information */
234
SourceLocation getSourceLocation();
235
}
236
```
237
238
### ProceedingJoinPoint Interface
239
240
Extended join point interface for around advice with execution control.
241
242
```java { .api }
243
interface ProceedingJoinPoint extends JoinPoint {
244
/** Proceed with original method execution */
245
Object proceed() throws Throwable;
246
247
/** Proceed with modified arguments */
248
Object proceed(Object[] args) throws Throwable;
249
}
250
```
251
252
### Signature Interface
253
254
Provides method signature information.
255
256
```java { .api }
257
interface Signature {
258
/** Get method name */
259
String getName();
260
261
/** Get declaring type */
262
Class<?> getDeclaringType();
263
264
/** Get method modifiers */
265
int getModifiers();
266
267
/** Get string representation */
268
String toString();
269
}
270
```
271
272
## Auto-Configuration Details
273
274
### AopAutoConfiguration
275
276
```java { .api }
277
/**
278
* Auto-configuration for Spring AOP support
279
* Equivalent to enabling @EnableAspectJAutoProxy
280
* Conditionally activated based on spring.aop.auto property
281
*/
282
@AutoConfiguration
283
@ConditionalOnBooleanProperty(name = "spring.aop.auto", matchIfMissing = true)
284
public class AopAutoConfiguration {
285
// Configuration classes for different proxy strategies
286
}
287
```
288
289
**Configuration Classes:**
290
- **AspectJAutoProxyingConfiguration**: Enabled when `org.aspectj.weaver.Advice` is on classpath
291
- **JdkDynamicAutoProxyConfiguration**: JDK dynamic proxies (interface-based) when `spring.aop.proxy-target-class=false`
292
- **CglibAutoProxyConfiguration**: CGLIB proxies (subclass-based) when `spring.aop.proxy-target-class=true` (default)
293
- **ClassProxyingConfiguration**: Fallback proxy configuration when AspectJ weaver not available
294
295
## Usage Examples
296
297
### Service Layer Monitoring
298
299
```java
300
@Aspect
301
@Component
302
public class ServiceMonitor {
303
304
private static final Logger logger = LoggerFactory.getLogger(ServiceMonitor.class);
305
306
@Around("execution(* com.example.service.*.*(..))")
307
public Object monitorServiceCall(ProceedingJoinPoint joinPoint) throws Throwable {
308
String methodName = joinPoint.getSignature().getName();
309
long startTime = System.currentTimeMillis();
310
311
try {
312
logger.info("Starting method: {}", methodName);
313
Object result = joinPoint.proceed();
314
long duration = System.currentTimeMillis() - startTime;
315
logger.info("Completed method: {} in {}ms", methodName, duration);
316
return result;
317
} catch (Exception e) {
318
logger.error("Method {} failed: {}", methodName, e.getMessage());
319
throw e;
320
}
321
}
322
}
323
```
324
325
### Security Aspect
326
327
```java
328
@Aspect
329
@Component
330
public class SecurityAspect {
331
332
@Before("@annotation(secured)")
333
public void checkSecurity(JoinPoint joinPoint, Secured secured) {
334
// Get current user context
335
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
336
337
if (auth == null || !auth.isAuthenticated()) {
338
throw new SecurityException("User not authenticated");
339
}
340
341
// Check required roles
342
String[] requiredRoles = secured.value();
343
boolean hasRole = Arrays.stream(requiredRoles)
344
.anyMatch(role -> auth.getAuthorities().stream()
345
.anyMatch(authority -> authority.getAuthority().equals(role)));
346
347
if (!hasRole) {
348
throw new SecurityException("Insufficient permissions");
349
}
350
}
351
}
352
```
353
354
### Transaction Management
355
356
```java
357
@Aspect
358
@Component
359
public class TransactionAspect {
360
361
@AfterThrowing(pointcut = "@annotation(transactional)", throwing = "exception")
362
public void handleTransactionException(JoinPoint joinPoint,
363
Transactional transactional,
364
Exception exception) {
365
// Custom transaction rollback logic
366
String methodName = joinPoint.getSignature().getName();
367
logger.error("Transaction rolled back for method: {} due to: {}",
368
methodName, exception.getMessage());
369
}
370
}
371
```
372
373
## Notes
374
375
- This starter automatically enables AOP when added to classpath
376
- No manual `@EnableAspectJAutoProxy` annotation required
377
- Supports both Spring AOP (proxy-based) and AspectJ (weaving-based) approaches
378
- Uses CGLIB proxies by default for maximum compatibility
379
- Aspects must be Spring beans (use `@Component` or equivalent)
380
- Pointcut expressions follow AspectJ syntax
381
- Performance impact: proxying adds minimal overhead for intercepted methods