0
# Annotation-Based Aspect Definition
1
2
Complete set of annotations for defining aspects using the @AspectJ syntax. This annotation-based approach allows aspects to be written as regular Java classes with special annotations, making them compatible with standard Java development tools and frameworks. Supports all AspectJ language features including advice, pointcuts, inter-type declarations, and aspect instantiation models.
3
4
## Capabilities
5
6
### Core Aspect Annotations
7
8
#### @Aspect
9
10
Declares a class as an aspect with optional instantiation model specification.
11
12
```java { .api }
13
/**
14
* Aspect declaration
15
*/
16
@Retention(RetentionPolicy.RUNTIME)
17
@Target(ElementType.TYPE)
18
public @interface Aspect {
19
/**
20
* The per clause expression, defaults to singleton aspect.
21
* Valid values are "" (singleton), "perthis(...)", "pertarget(...)",
22
* "pertypewithin(...)", "percflow(...)", "percflowbelow(...)"
23
*/
24
String value() default "";
25
}
26
```
27
28
**Usage Examples:**
29
30
```java
31
// Singleton aspect (default)
32
@Aspect
33
public class LoggingAspect {
34
// aspect implementation
35
}
36
37
// Per-object aspect
38
@Aspect("perthis(execution(* com.example.service.*.*(..)))")
39
public class ServiceMonitorAspect {
40
// per-instance state and behavior
41
}
42
43
// Per-type-within aspect
44
@Aspect("pertypewithin(com.example.model.*)")
45
public class EntityAuditAspect {
46
// per-type state and behavior
47
}
48
```
49
50
#### @Pointcut
51
52
Declares a named pointcut that can be referenced by advice and other pointcuts.
53
54
```java { .api }
55
/**
56
* Pointcut declaration
57
*/
58
@Retention(RetentionPolicy.RUNTIME)
59
@Target(ElementType.METHOD)
60
public @interface Pointcut {
61
/**
62
* The pointcut expression. Can be empty for abstract pointcuts.
63
*/
64
String value() default "";
65
66
/**
67
* Argument names for runtime interpretation when debug info is not available.
68
* Format is a simple comma-separated list.
69
*/
70
String argNames() default "";
71
}
72
```
73
74
**Usage Examples:**
75
76
```java
77
@Aspect
78
public class SecurityAspect {
79
80
@Pointcut("execution(* com.example.service.*.*(..))")
81
public void serviceLayer() {}
82
83
@Pointcut("@annotation(com.example.security.Secured)")
84
public void securedMethods() {}
85
86
@Pointcut("serviceLayer() && securedMethods()")
87
public void securedServiceMethods() {}
88
89
@Pointcut("execution(* *.save*(..)) && args(entity)")
90
public void saveOperations(Object entity) {}
91
}
92
```
93
94
### Advice Annotations
95
96
#### @Before
97
98
Declares before advice that executes before join point execution.
99
100
```java { .api }
101
/**
102
* Before advice
103
*/
104
@Retention(RetentionPolicy.RUNTIME)
105
@Target(ElementType.METHOD)
106
public @interface Before {
107
/**
108
* The pointcut expression where to bind the advice
109
*/
110
String value();
111
112
/**
113
* Argument names for runtime interpretation when debug info is not available
114
*/
115
String argNames() default "";
116
}
117
```
118
119
#### @After
120
121
Declares after advice that executes after join point completion (finally behavior).
122
123
```java { .api }
124
/**
125
* After advice (after finally)
126
*/
127
@Retention(RetentionPolicy.RUNTIME)
128
@Target(ElementType.METHOD)
129
public @interface After {
130
/**
131
* The pointcut expression where to bind the advice
132
*/
133
String value();
134
135
/**
136
* Argument names for runtime interpretation when debug info is not available
137
*/
138
String argNames() default "";
139
}
140
```
141
142
#### @AfterReturning
143
144
Declares after returning advice that executes after successful join point completion.
145
146
```java { .api }
147
/**
148
* After returning advice
149
*/
150
@Retention(RetentionPolicy.RUNTIME)
151
@Target(ElementType.METHOD)
152
public @interface AfterReturning {
153
/**
154
* The pointcut expression where to bind the advice
155
*/
156
String value() default "";
157
158
/**
159
* Alternative pointcut expression, overrides "value" when specified
160
*/
161
String pointcut() default "";
162
163
/**
164
* The name of the argument in the advice signature to bind the returned value to
165
*/
166
String returning() default "";
167
168
/**
169
* Argument names for runtime interpretation when debug info is not available
170
*/
171
String argNames() default "";
172
}
173
```
174
175
#### @AfterThrowing
176
177
Declares after throwing advice that executes when join point throws an exception.
178
179
```java { .api }
180
/**
181
* After throwing advice
182
*/
183
@Retention(RetentionPolicy.RUNTIME)
184
@Target(ElementType.METHOD)
185
public @interface AfterThrowing {
186
/**
187
* The pointcut expression where to bind the advice
188
*/
189
String value() default "";
190
191
/**
192
* Alternative pointcut expression, overrides "value" when specified
193
*/
194
String pointcut() default "";
195
196
/**
197
* The name of the argument in the advice signature to bind the thrown exception to
198
*/
199
String throwing() default "";
200
201
/**
202
* Argument names for runtime interpretation when debug info is not available
203
*/
204
String argNames() default "";
205
}
206
```
207
208
#### @Around
209
210
Declares around advice that can control join point execution.
211
212
```java { .api }
213
/**
214
* Around advice
215
*/
216
@Retention(RetentionPolicy.RUNTIME)
217
@Target(ElementType.METHOD)
218
public @interface Around {
219
/**
220
* The pointcut expression where to bind the advice
221
*/
222
String value();
223
224
/**
225
* Argument names for runtime interpretation when debug info is not available
226
*/
227
String argNames() default "";
228
}
229
```
230
231
**Complete Advice Usage Example:**
232
233
```java
234
@Aspect
235
public class ComprehensiveLoggingAspect {
236
237
@Pointcut("execution(* com.example.service.*.*(..))")
238
public void serviceLayer() {}
239
240
@Before("serviceLayer()")
241
public void logBefore(JoinPoint joinPoint) {
242
System.out.println("==> Entering: " + joinPoint.getSignature().toShortString());
243
}
244
245
@AfterReturning(pointcut = "serviceLayer()", returning = "result")
246
public void logAfterReturning(JoinPoint joinPoint, Object result) {
247
System.out.println("<== Successfully returned from: " +
248
joinPoint.getSignature().toShortString() +
249
" with result: " + result);
250
}
251
252
@AfterThrowing(pointcut = "serviceLayer()", throwing = "ex")
253
public void logAfterThrowing(JoinPoint joinPoint, Throwable ex) {
254
System.out.println("*** Exception in: " +
255
joinPoint.getSignature().toShortString() +
256
" - " + ex.getMessage());
257
}
258
259
@After("serviceLayer()")
260
public void logAfter(JoinPoint joinPoint) {
261
System.out.println("--- Completed: " + joinPoint.getSignature().toShortString());
262
}
263
264
@Around("serviceLayer()")
265
public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
266
long start = System.currentTimeMillis();
267
try {
268
Object result = pjp.proceed();
269
long duration = System.currentTimeMillis() - start;
270
System.out.println("Executed " + pjp.getSignature().toShortString() +
271
" in " + duration + " ms");
272
return result;
273
} catch (Throwable t) {
274
long duration = System.currentTimeMillis() - start;
275
System.out.println("Failed " + pjp.getSignature().toShortString() +
276
" after " + duration + " ms");
277
throw t;
278
}
279
}
280
}
281
```
282
283
### Declaration Annotations
284
285
#### @DeclareParents
286
287
Declares inter-type declarations (mixins) for adding interfaces and implementations to existing types.
288
289
```java { .api }
290
/**
291
* Declare parents mixin annotation
292
*/
293
@Retention(RetentionPolicy.RUNTIME)
294
@Target(ElementType.FIELD)
295
public @interface DeclareParents {
296
/**
297
* The target types expression (type pattern)
298
*/
299
String value();
300
301
/**
302
* Optional class defining default implementation of interface members.
303
* Equivalent to defining a set of interface member ITDs for the
304
* public methods of the interface.
305
*/
306
Class defaultImpl() default DeclareParents.class;
307
}
308
```
309
310
**Usage Examples:**
311
312
```java
313
@Aspect
314
public class MixinAspect {
315
316
// Add Auditable interface to all model classes
317
@DeclareParents(value = "com.example.model.*", defaultImpl = AuditableImpl.class)
318
private Auditable auditableIntroduction;
319
320
// Add Cacheable interface without implementation (must be implemented elsewhere)
321
@DeclareParents("com.example.service.*")
322
private Cacheable cacheableIntroduction;
323
}
324
325
public interface Auditable {
326
void setLastModified(Date date);
327
Date getLastModified();
328
void setModifiedBy(String user);
329
String getModifiedBy();
330
}
331
332
public class AuditableImpl implements Auditable {
333
private Date lastModified;
334
private String modifiedBy;
335
336
public void setLastModified(Date date) { this.lastModified = date; }
337
public Date getLastModified() { return lastModified; }
338
public void setModifiedBy(String user) { this.modifiedBy = user; }
339
public String getModifiedBy() { return modifiedBy; }
340
}
341
```
342
343
#### @DeclareError and @DeclareWarning
344
345
Declare compile-time errors and warnings for specific join points.
346
347
```java { .api }
348
/**
349
* Declare compile-time error
350
*/
351
@Retention(RetentionPolicy.RUNTIME)
352
@Target(ElementType.METHOD)
353
public @interface DeclareError {
354
/**
355
* The pointcut expression where to trigger the error
356
*/
357
String value();
358
}
359
360
/**
361
* Declare compile-time warning
362
*/
363
@Retention(RetentionPolicy.RUNTIME)
364
@Target(ElementType.METHOD)
365
public @interface DeclareWarning {
366
/**
367
* The pointcut expression where to trigger the warning
368
*/
369
String value();
370
}
371
```
372
373
**Usage Examples:**
374
375
```java
376
@Aspect
377
public class ComplianceAspect {
378
379
@DeclareError("call(* java.sql.Connection.createStatement(..))")
380
public static final String NO_DIRECT_SQL =
381
"Direct SQL statements are prohibited - use prepared statements";
382
383
@DeclareWarning("execution(* com.example.*.*(..)) && !@annotation(Deprecated)")
384
public static final String MISSING_DOCUMENTATION =
385
"Public methods should have proper documentation";
386
}
387
```
388
389
### Other Annotation Features
390
391
#### @AdviceName
392
393
Provides explicit names for advice methods to improve debugging and profiling.
394
395
```java { .api }
396
/**
397
* Names advice for better debugging/profiling
398
*/
399
@Retention(RetentionPolicy.RUNTIME)
400
@Target(ElementType.METHOD)
401
public @interface AdviceName {
402
/**
403
* The name for the advice
404
*/
405
String value();
406
}
407
```
408
409
#### @SuppressAjWarnings
410
411
Suppresses AspectJ compiler warnings for specific advice or aspects.
412
413
```java { .api }
414
/**
415
* Suppress AspectJ compiler warnings
416
*/
417
@Retention(RetentionPolicy.RUNTIME)
418
@Target({ElementType.TYPE, ElementType.METHOD})
419
public @interface SuppressAjWarnings {
420
/**
421
* Warning types to suppress
422
*/
423
String[] value();
424
}
425
```
426
427
**Usage Examples:**
428
429
```java
430
@Aspect
431
public class OptimizedAspect {
432
433
@AdviceName("performanceTracker")
434
@Around("execution(* com.example.critical.*.*(..))")
435
public Object trackPerformance(ProceedingJoinPoint pjp) throws Throwable {
436
// Performance tracking logic
437
return pjp.proceed();
438
}
439
440
@SuppressAjWarnings({"adviceDidNotMatch", "uncheckedArgTypes"})
441
@Before("call(* com.legacy..*.*(..))")
442
public void handleLegacyCall() {
443
// Legacy integration code that may trigger warnings
444
}
445
}
446
```
447
448
## Argument Binding and Runtime Support
449
450
### Argument Names
451
452
When compiling without debug information or interpreting pointcuts at runtime, argument names must be explicitly provided:
453
454
```java
455
@Aspect
456
public class ArgumentBindingAspect {
457
458
@Before(value = "execution(* com.example.service.*.save(..)) && args(entity, options)",
459
argNames = "entity,options")
460
public void validateSave(Object entity, Map<String, Object> options) {
461
// Validation logic
462
}
463
464
@AfterReturning(pointcut = "execution(* com.example.service.*.find(..))",
465
returning = "result",
466
argNames = "result")
467
public void logResult(Object result) {
468
// Result logging
469
}
470
}
471
```
472
473
### Integration with Standard Java
474
475
@AspectJ aspects are regular Java classes and can:
476
477
- Use standard Java annotations alongside AspectJ annotations
478
- Implement interfaces and extend classes
479
- Be managed by dependency injection frameworks
480
- Use standard Java compilation and tooling
481
482
```java
483
@Aspect
484
@Component // Spring annotation
485
@Transactional // JPA annotation
486
public class IntegratedAspect {
487
488
@Autowired
489
private AuditService auditService;
490
491
@PostConstruct
492
public void initialize() {
493
System.out.println("Aspect initialized");
494
}
495
496
@Before("@annotation(Audited)")
497
public void auditOperation(JoinPoint joinPoint) {
498
auditService.recordOperation(joinPoint.getSignature().getName());
499
}
500
}
501
```