0
# Join Point Introspection
1
2
Core runtime interfaces that provide reflective access to join points - the specific points in program execution where aspects can be applied. Join points represent method calls, method executions, field access, constructor calls, exception handlers, and other program execution events. The introspection API provides access to execution context, arguments, target objects, source location, and signature information.
3
4
## Capabilities
5
6
### JoinPoint Interface
7
8
The fundamental interface providing reflective access to both the state available at a join point and static information about it. Available in advice using the special form `thisJoinPoint`.
9
10
```java { .api }
11
/**
12
* Provides reflective access to both the state available at a join point and
13
* static information about it. This information is available from the body
14
* of advice using the special form thisJoinPoint.
15
*/
16
public interface JoinPoint {
17
/**
18
* Returns the currently executing object. This will always be
19
* the same object as that matched by the this pointcut designator.
20
* Returns null when there is no currently executing object available
21
* (e.g. static context).
22
*/
23
Object getThis();
24
25
/**
26
* Returns the target object. This will always be the same object
27
* as that matched by the target pointcut designator.
28
* Returns null when there is no target object.
29
*/
30
Object getTarget();
31
32
/**
33
* Returns the arguments at this join point
34
*/
35
Object[] getArgs();
36
37
/**
38
* Returns the signature at the join point
39
*/
40
Signature getSignature();
41
42
/**
43
* Returns the source location corresponding to the join point.
44
* If there is no source location available, returns null.
45
* Returns the SourceLocation of the defining class for default constructors.
46
*/
47
SourceLocation getSourceLocation();
48
49
/**
50
* Returns a string representing the kind of join point.
51
* This string is guaranteed to be interned.
52
*/
53
String getKind();
54
55
/**
56
* Returns an object that encapsulates the static parts of this join point
57
*/
58
StaticPart getStaticPart();
59
60
/**
61
* String representation of this join point
62
*/
63
String toString();
64
65
/**
66
* Returns an abbreviated string representation of the join point
67
*/
68
String toShortString();
69
70
/**
71
* Returns an extended string representation of the join point
72
*/
73
String toLongString();
74
}
75
```
76
77
**Usage Examples:**
78
79
```java
80
import org.aspectj.lang.JoinPoint;
81
import org.aspectj.lang.annotation.Aspect;
82
import org.aspectj.lang.annotation.Before;
83
84
@Aspect
85
public class LoggingAspect {
86
87
@Before("execution(* com.example.service.*.*(..))")
88
public void logMethodEntry(JoinPoint joinPoint) {
89
System.out.println("Entering: " + joinPoint.getSignature().getName());
90
System.out.println("Target: " + joinPoint.getTarget());
91
System.out.println("Args: " + Arrays.toString(joinPoint.getArgs()));
92
System.out.println("Kind: " + joinPoint.getKind());
93
System.out.println("Location: " + joinPoint.getSourceLocation());
94
}
95
}
96
```
97
98
### ProceedingJoinPoint Interface
99
100
Extends JoinPoint to expose the `proceed()` method for around advice in @AspectJ aspects. Allows advice to control whether and how the intercepted join point continues execution.
101
102
```java { .api }
103
/**
104
* ProceedingJoinPoint exposes the proceed(..) method in order to support
105
* around advice in @AJ aspects
106
*/
107
public interface ProceedingJoinPoint extends JoinPoint {
108
/**
109
* Proceed with the next advice or target method invocation
110
* @return the result of proceeding
111
* @throws Throwable if the invoked proceed throws anything
112
*/
113
Object proceed() throws Throwable;
114
115
/**
116
* Proceed with the next advice or target method invocation using modified arguments.
117
* The proceed(..) call takes arguments in this order:
118
* 1. If 'this()' was used in the pointcut for binding, it must be passed first
119
* 2. If 'target()' was used in the pointcut for binding, it must be passed next
120
* 3. All the arguments expected at the join point, in the order they are supplied
121
*
122
* @param args the arguments to proceed with
123
* @return the result of proceeding
124
* @throws Throwable if the invoked proceed throws anything
125
*/
126
Object proceed(Object[] args) throws Throwable;
127
}
128
```
129
130
**Usage Examples:**
131
132
```java
133
import org.aspectj.lang.ProceedingJoinPoint;
134
import org.aspectj.lang.annotation.Around;
135
import org.aspectj.lang.annotation.Aspect;
136
137
@Aspect
138
public class TimingAspect {
139
140
@Around("execution(* com.example.service.*.*(..))")
141
public Object measureExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
142
long startTime = System.currentTimeMillis();
143
144
try {
145
// Proceed with original method execution
146
Object result = joinPoint.proceed();
147
return result;
148
} finally {
149
long executionTime = System.currentTimeMillis() - startTime;
150
System.out.println("Method " + joinPoint.getSignature().getName() +
151
" executed in " + executionTime + " ms");
152
}
153
}
154
155
@Around("execution(* com.example.service.*.*(String, ..)) && args(firstArg, ..)")
156
public Object interceptWithModifiedArgs(ProceedingJoinPoint joinPoint, String firstArg) throws Throwable {
157
Object[] args = joinPoint.getArgs();
158
159
// Modify the first argument
160
args[0] = "Modified: " + firstArg;
161
162
// Proceed with modified arguments
163
return joinPoint.proceed(args);
164
}
165
}
166
```
167
168
### JoinPoint.StaticPart Interface
169
170
Contains only the static information about a join point. Available separately within advice using the special form `thisJoinPointStaticPart`. Use this for better performance when only static information is needed.
171
172
```java { .api }
173
/**
174
* This helper object contains only the static information about a join point.
175
* If you are only interested in the static information about a join point,
176
* you should access it through this type for the best performance.
177
*/
178
public interface StaticPart {
179
/**
180
* Returns the signature at the join point
181
*/
182
Signature getSignature();
183
184
/**
185
* Returns the source location corresponding to the join point.
186
* If there is no source location available, returns null.
187
*/
188
SourceLocation getSourceLocation();
189
190
/**
191
* Returns a string representing the kind of join point.
192
* This String is guaranteed to be interned.
193
*/
194
String getKind();
195
196
/**
197
* Return the id for this JoinPoint.StaticPart. All JoinPoint.StaticPart
198
* instances are assigned an id number upon creation. For each advised type
199
* the id numbers start at 0. The id is guaranteed to remain constant
200
* across repeated executions but may change if the code is recompiled.
201
*/
202
int getId();
203
204
String toString();
205
String toShortString();
206
String toLongString();
207
}
208
```
209
210
**Usage Examples:**
211
212
```java
213
@Aspect
214
public class StaticAnalysisAspect {
215
216
@Before("execution(* com.example..*.*(..))")
217
public void analyzeJoinPoint(JoinPoint.StaticPart staticPart) {
218
System.out.println("Join Point ID: " + staticPart.getId());
219
System.out.println("Kind: " + staticPart.getKind());
220
System.out.println("Signature: " + staticPart.getSignature());
221
System.out.println("Location: " + staticPart.getSourceLocation());
222
}
223
}
224
```
225
226
### Join Point Kinds
227
228
Constants representing the different types of join points that can be intercepted:
229
230
```java { .api }
231
public interface JoinPoint {
232
// Method-related join points
233
String METHOD_EXECUTION = "method-execution";
234
String METHOD_CALL = "method-call";
235
236
// Constructor-related join points
237
String CONSTRUCTOR_EXECUTION = "constructor-execution";
238
String CONSTRUCTOR_CALL = "constructor-call";
239
240
// Field-related join points
241
String FIELD_GET = "field-get";
242
String FIELD_SET = "field-set";
243
244
// Initialization join points
245
String STATICINITIALIZATION = "staticinitialization";
246
String PREINITIALIZATION = "preinitialization";
247
String INITIALIZATION = "initialization";
248
249
// Exception and synchronization join points
250
String EXCEPTION_HANDLER = "exception-handler";
251
String SYNCHRONIZATION_LOCK = "lock";
252
String SYNCHRONIZATION_UNLOCK = "unlock";
253
254
// Advice execution join point
255
String ADVICE_EXECUTION = "adviceexecution";
256
}
257
```
258
259
### EnclosingStaticPart Interface
260
261
Marker interface extending StaticPart for enclosing join point information:
262
263
```java { .api }
264
/**
265
* Marker interface for enclosing static part information
266
*/
267
public interface EnclosingStaticPart extends StaticPart {
268
}
269
```
270
271
## Common Usage Patterns
272
273
### Basic Join Point Logging
274
275
```java
276
@Aspect
277
public class BasicLoggingAspect {
278
279
@Before("execution(* com.example..*.*(..))")
280
public void logEntry(JoinPoint jp) {
281
System.out.println("==> " + jp.toShortString());
282
}
283
284
@AfterReturning(pointcut = "execution(* com.example..*.*(..))", returning = "result")
285
public void logExit(JoinPoint jp, Object result) {
286
System.out.println("<== " + jp.toShortString() + " returned " + result);
287
}
288
}
289
```
290
291
### Performance Monitoring
292
293
```java
294
@Aspect
295
public class PerformanceAspect {
296
297
@Around("execution(* com.example.service.*.*(..))")
298
public Object monitorPerformance(ProceedingJoinPoint pjp) throws Throwable {
299
long start = System.nanoTime();
300
String methodName = pjp.getSignature().toShortString();
301
302
try {
303
Object result = pjp.proceed();
304
long duration = System.nanoTime() - start;
305
System.out.printf("%s completed in %.2f ms%n",
306
methodName, duration / 1_000_000.0);
307
return result;
308
} catch (Exception e) {
309
long duration = System.nanoTime() - start;
310
System.out.printf("%s failed after %.2f ms: %s%n",
311
methodName, duration / 1_000_000.0, e.getMessage());
312
throw e;
313
}
314
}
315
}
316
```
317
318
### Argument Validation and Modification
319
320
```java
321
@Aspect
322
public class ValidationAspect {
323
324
@Around("execution(* com.example.service.*.save*(..)) && args(entity, ..)")
325
public Object validateAndProceed(ProceedingJoinPoint pjp, Object entity) throws Throwable {
326
if (entity == null) {
327
throw new IllegalArgumentException("Entity cannot be null for " +
328
pjp.getSignature().getName());
329
}
330
331
// Log the validation
332
System.out.println("Validating " + entity.getClass().getSimpleName() +
333
" for " + pjp.getSignature().getName());
334
335
return pjp.proceed();
336
}
337
}
338
```