The AspectJ runtime is a small library necessary to run Java programs enhanced by AspectJ aspects during a previous compile-time or post-compile-time (binary weaving) build step.
—
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.
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.
/**
* Provides reflective access to both the state available at a join point and
* static information about it. This information is available from the body
* of advice using the special form thisJoinPoint.
*/
public interface JoinPoint {
/**
* Returns the currently executing object. This will always be
* the same object as that matched by the this pointcut designator.
* Returns null when there is no currently executing object available
* (e.g. static context).
*/
Object getThis();
/**
* Returns the target object. This will always be the same object
* as that matched by the target pointcut designator.
* Returns null when there is no target object.
*/
Object getTarget();
/**
* Returns the arguments at this join point
*/
Object[] getArgs();
/**
* Returns the signature at the join point
*/
Signature getSignature();
/**
* Returns the source location corresponding to the join point.
* If there is no source location available, returns null.
* Returns the SourceLocation of the defining class for default constructors.
*/
SourceLocation getSourceLocation();
/**
* Returns a string representing the kind of join point.
* This string is guaranteed to be interned.
*/
String getKind();
/**
* Returns an object that encapsulates the static parts of this join point
*/
StaticPart getStaticPart();
/**
* String representation of this join point
*/
String toString();
/**
* Returns an abbreviated string representation of the join point
*/
String toShortString();
/**
* Returns an extended string representation of the join point
*/
String toLongString();
}Usage Examples:
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logMethodEntry(JoinPoint joinPoint) {
System.out.println("Entering: " + joinPoint.getSignature().getName());
System.out.println("Target: " + joinPoint.getTarget());
System.out.println("Args: " + Arrays.toString(joinPoint.getArgs()));
System.out.println("Kind: " + joinPoint.getKind());
System.out.println("Location: " + joinPoint.getSourceLocation());
}
}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.
/**
* ProceedingJoinPoint exposes the proceed(..) method in order to support
* around advice in @AJ aspects
*/
public interface ProceedingJoinPoint extends JoinPoint {
/**
* Proceed with the next advice or target method invocation
* @return the result of proceeding
* @throws Throwable if the invoked proceed throws anything
*/
Object proceed() throws Throwable;
/**
* Proceed with the next advice or target method invocation using modified arguments.
* The proceed(..) call takes arguments in this order:
* 1. If 'this()' was used in the pointcut for binding, it must be passed first
* 2. If 'target()' was used in the pointcut for binding, it must be passed next
* 3. All the arguments expected at the join point, in the order they are supplied
*
* @param args the arguments to proceed with
* @return the result of proceeding
* @throws Throwable if the invoked proceed throws anything
*/
Object proceed(Object[] args) throws Throwable;
}Usage Examples:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class TimingAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object measureExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
try {
// Proceed with original method execution
Object result = joinPoint.proceed();
return result;
} finally {
long executionTime = System.currentTimeMillis() - startTime;
System.out.println("Method " + joinPoint.getSignature().getName() +
" executed in " + executionTime + " ms");
}
}
@Around("execution(* com.example.service.*.*(String, ..)) && args(firstArg, ..)")
public Object interceptWithModifiedArgs(ProceedingJoinPoint joinPoint, String firstArg) throws Throwable {
Object[] args = joinPoint.getArgs();
// Modify the first argument
args[0] = "Modified: " + firstArg;
// Proceed with modified arguments
return joinPoint.proceed(args);
}
}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.
/**
* This helper object contains only the static information about a join point.
* If you are only interested in the static information about a join point,
* you should access it through this type for the best performance.
*/
public interface StaticPart {
/**
* Returns the signature at the join point
*/
Signature getSignature();
/**
* Returns the source location corresponding to the join point.
* If there is no source location available, returns null.
*/
SourceLocation getSourceLocation();
/**
* Returns a string representing the kind of join point.
* This String is guaranteed to be interned.
*/
String getKind();
/**
* Return the id for this JoinPoint.StaticPart. All JoinPoint.StaticPart
* instances are assigned an id number upon creation. For each advised type
* the id numbers start at 0. The id is guaranteed to remain constant
* across repeated executions but may change if the code is recompiled.
*/
int getId();
String toString();
String toShortString();
String toLongString();
}Usage Examples:
@Aspect
public class StaticAnalysisAspect {
@Before("execution(* com.example..*.*(..))")
public void analyzeJoinPoint(JoinPoint.StaticPart staticPart) {
System.out.println("Join Point ID: " + staticPart.getId());
System.out.println("Kind: " + staticPart.getKind());
System.out.println("Signature: " + staticPart.getSignature());
System.out.println("Location: " + staticPart.getSourceLocation());
}
}Constants representing the different types of join points that can be intercepted:
public interface JoinPoint {
// Method-related join points
String METHOD_EXECUTION = "method-execution";
String METHOD_CALL = "method-call";
// Constructor-related join points
String CONSTRUCTOR_EXECUTION = "constructor-execution";
String CONSTRUCTOR_CALL = "constructor-call";
// Field-related join points
String FIELD_GET = "field-get";
String FIELD_SET = "field-set";
// Initialization join points
String STATICINITIALIZATION = "staticinitialization";
String PREINITIALIZATION = "preinitialization";
String INITIALIZATION = "initialization";
// Exception and synchronization join points
String EXCEPTION_HANDLER = "exception-handler";
String SYNCHRONIZATION_LOCK = "lock";
String SYNCHRONIZATION_UNLOCK = "unlock";
// Advice execution join point
String ADVICE_EXECUTION = "adviceexecution";
}Marker interface extending StaticPart for enclosing join point information:
/**
* Marker interface for enclosing static part information
*/
public interface EnclosingStaticPart extends StaticPart {
}@Aspect
public class BasicLoggingAspect {
@Before("execution(* com.example..*.*(..))")
public void logEntry(JoinPoint jp) {
System.out.println("==> " + jp.toShortString());
}
@AfterReturning(pointcut = "execution(* com.example..*.*(..))", returning = "result")
public void logExit(JoinPoint jp, Object result) {
System.out.println("<== " + jp.toShortString() + " returned " + result);
}
}@Aspect
public class PerformanceAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object monitorPerformance(ProceedingJoinPoint pjp) throws Throwable {
long start = System.nanoTime();
String methodName = pjp.getSignature().toShortString();
try {
Object result = pjp.proceed();
long duration = System.nanoTime() - start;
System.out.printf("%s completed in %.2f ms%n",
methodName, duration / 1_000_000.0);
return result;
} catch (Exception e) {
long duration = System.nanoTime() - start;
System.out.printf("%s failed after %.2f ms: %s%n",
methodName, duration / 1_000_000.0, e.getMessage());
throw e;
}
}
}@Aspect
public class ValidationAspect {
@Around("execution(* com.example.service.*.save*(..)) && args(entity, ..)")
public Object validateAndProceed(ProceedingJoinPoint pjp, Object entity) throws Throwable {
if (entity == null) {
throw new IllegalArgumentException("Entity cannot be null for " +
pjp.getSignature().getName());
}
// Log the validation
System.out.println("Validating " + entity.getClass().getSimpleName() +
" for " + pjp.getSignature().getName());
return pjp.proceed();
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-aspectj--aspectjrt