CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-aspectj--aspectjrt

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.

Pending
Overview
Eval results
Files

annotation-based-definition.mddocs/

Annotation-Based Aspect Definition

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.

Capabilities

Core Aspect Annotations

@Aspect

Declares a class as an aspect with optional instantiation model specification.

/**
 * Aspect declaration
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Aspect {
    /**
     * The per clause expression, defaults to singleton aspect.
     * Valid values are "" (singleton), "perthis(...)", "pertarget(...)", 
     * "pertypewithin(...)", "percflow(...)", "percflowbelow(...)"
     */
    String value() default "";
}

Usage Examples:

// Singleton aspect (default)
@Aspect
public class LoggingAspect {
    // aspect implementation
}

// Per-object aspect
@Aspect("perthis(execution(* com.example.service.*.*(..)))")
public class ServiceMonitorAspect {
    // per-instance state and behavior
}

// Per-type-within aspect  
@Aspect("pertypewithin(com.example.model.*)")
public class EntityAuditAspect {
    // per-type state and behavior
}

@Pointcut

Declares a named pointcut that can be referenced by advice and other pointcuts.

/**
 * Pointcut declaration
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Pointcut {
    /**
     * The pointcut expression. Can be empty for abstract pointcuts.
     */
    String value() default "";
    
    /**
     * Argument names for runtime interpretation when debug info is not available.
     * Format is a simple comma-separated list.
     */
    String argNames() default "";
}

Usage Examples:

@Aspect
public class SecurityAspect {
    
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceLayer() {}
    
    @Pointcut("@annotation(com.example.security.Secured)")
    public void securedMethods() {}
    
    @Pointcut("serviceLayer() && securedMethods()")
    public void securedServiceMethods() {}
    
    @Pointcut("execution(* *.save*(..)) && args(entity)")
    public void saveOperations(Object entity) {}
}

Advice Annotations

@Before

Declares before advice that executes before join point execution.

/**
 * Before advice
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Before {
    /**
     * The pointcut expression where to bind the advice
     */
    String value();
    
    /**
     * Argument names for runtime interpretation when debug info is not available
     */
    String argNames() default "";
}

@After

Declares after advice that executes after join point completion (finally behavior).

/**
 * After advice (after finally)
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) 
public @interface After {
    /**
     * The pointcut expression where to bind the advice
     */
    String value();
    
    /**
     * Argument names for runtime interpretation when debug info is not available
     */
    String argNames() default "";
}

@AfterReturning

Declares after returning advice that executes after successful join point completion.

/**
 * After returning advice
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AfterReturning {
    /**
     * The pointcut expression where to bind the advice
     */
    String value() default "";
    
    /**
     * Alternative pointcut expression, overrides "value" when specified
     */
    String pointcut() default "";
    
    /**
     * The name of the argument in the advice signature to bind the returned value to
     */
    String returning() default "";
    
    /**
     * Argument names for runtime interpretation when debug info is not available
     */
    String argNames() default "";
}

@AfterThrowing

Declares after throwing advice that executes when join point throws an exception.

/**
 * After throwing advice
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AfterThrowing {
    /**
     * The pointcut expression where to bind the advice
     */
    String value() default "";
    
    /**
     * Alternative pointcut expression, overrides "value" when specified
     */
    String pointcut() default "";
    
    /**
     * The name of the argument in the advice signature to bind the thrown exception to
     */
    String throwing() default "";
    
    /**
     * Argument names for runtime interpretation when debug info is not available
     */
    String argNames() default "";
}

@Around

Declares around advice that can control join point execution.

/**
 * Around advice
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Around {
    /**
     * The pointcut expression where to bind the advice
     */
    String value();
    
    /**
     * Argument names for runtime interpretation when debug info is not available
     */
    String argNames() default "";
}

Complete Advice Usage Example:

@Aspect
public class ComprehensiveLoggingAspect {
    
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceLayer() {}
    
    @Before("serviceLayer()")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("==> Entering: " + joinPoint.getSignature().toShortString());
    }
    
    @AfterReturning(pointcut = "serviceLayer()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        System.out.println("<== Successfully returned from: " + 
                          joinPoint.getSignature().toShortString() + 
                          " with result: " + result);
    }
    
    @AfterThrowing(pointcut = "serviceLayer()", throwing = "ex")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable ex) {
        System.out.println("*** Exception in: " + 
                          joinPoint.getSignature().toShortString() + 
                          " - " + ex.getMessage());
    }
    
    @After("serviceLayer()")
    public void logAfter(JoinPoint joinPoint) {
        System.out.println("--- Completed: " + joinPoint.getSignature().toShortString());
    }
    
    @Around("serviceLayer()")
    public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.currentTimeMillis();
        try {
            Object result = pjp.proceed();
            long duration = System.currentTimeMillis() - start;
            System.out.println("Executed " + pjp.getSignature().toShortString() + 
                             " in " + duration + " ms");
            return result;
        } catch (Throwable t) {
            long duration = System.currentTimeMillis() - start;
            System.out.println("Failed " + pjp.getSignature().toShortString() + 
                             " after " + duration + " ms");
            throw t;
        }
    }
}

Declaration Annotations

@DeclareParents

Declares inter-type declarations (mixins) for adding interfaces and implementations to existing types.

/**
 * Declare parents mixin annotation
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DeclareParents {
    /**
     * The target types expression (type pattern)
     */
    String value();
    
    /**
     * Optional class defining default implementation of interface members.
     * Equivalent to defining a set of interface member ITDs for the
     * public methods of the interface.
     */
    Class defaultImpl() default DeclareParents.class;
}

Usage Examples:

@Aspect
public class MixinAspect {
    
    // Add Auditable interface to all model classes
    @DeclareParents(value = "com.example.model.*", defaultImpl = AuditableImpl.class)
    private Auditable auditableIntroduction;
    
    // Add Cacheable interface without implementation (must be implemented elsewhere)
    @DeclareParents("com.example.service.*")
    private Cacheable cacheableIntroduction;
}

public interface Auditable {
    void setLastModified(Date date);
    Date getLastModified();
    void setModifiedBy(String user);
    String getModifiedBy();
}

public class AuditableImpl implements Auditable {
    private Date lastModified;
    private String modifiedBy;
    
    public void setLastModified(Date date) { this.lastModified = date; }
    public Date getLastModified() { return lastModified; }
    public void setModifiedBy(String user) { this.modifiedBy = user; }
    public String getModifiedBy() { return modifiedBy; }
}

@DeclareError and @DeclareWarning

Declare compile-time errors and warnings for specific join points.

/**
 * Declare compile-time error
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DeclareError {
    /**
     * The pointcut expression where to trigger the error
     */
    String value();
}

/**
 * Declare compile-time warning  
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DeclareWarning {
    /**
     * The pointcut expression where to trigger the warning
     */
    String value();
}

Usage Examples:

@Aspect
public class ComplianceAspect {
    
    @DeclareError("call(* java.sql.Connection.createStatement(..))")
    public static final String NO_DIRECT_SQL = 
        "Direct SQL statements are prohibited - use prepared statements";
    
    @DeclareWarning("execution(* com.example.*.*(..)) && !@annotation(Deprecated)")
    public static final String MISSING_DOCUMENTATION = 
        "Public methods should have proper documentation";
}

Other Annotation Features

@AdviceName

Provides explicit names for advice methods to improve debugging and profiling.

/**
 * Names advice for better debugging/profiling
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AdviceName {
    /**
     * The name for the advice
     */
    String value();
}

@SuppressAjWarnings

Suppresses AspectJ compiler warnings for specific advice or aspects.

/**
 * Suppress AspectJ compiler warnings
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface SuppressAjWarnings {
    /**
     * Warning types to suppress
     */
    String[] value();
}

Usage Examples:

@Aspect
public class OptimizedAspect {
    
    @AdviceName("performanceTracker")
    @Around("execution(* com.example.critical.*.*(..))")
    public Object trackPerformance(ProceedingJoinPoint pjp) throws Throwable {
        // Performance tracking logic
        return pjp.proceed();
    }
    
    @SuppressAjWarnings({"adviceDidNotMatch", "uncheckedArgTypes"})
    @Before("call(* com.legacy..*.*(..))")
    public void handleLegacyCall() {
        // Legacy integration code that may trigger warnings
    }
}

Argument Binding and Runtime Support

Argument Names

When compiling without debug information or interpreting pointcuts at runtime, argument names must be explicitly provided:

@Aspect
public class ArgumentBindingAspect {
    
    @Before(value = "execution(* com.example.service.*.save(..)) && args(entity, options)", 
            argNames = "entity,options")
    public void validateSave(Object entity, Map<String, Object> options) {
        // Validation logic
    }
    
    @AfterReturning(pointcut = "execution(* com.example.service.*.find(..))", 
                    returning = "result", 
                    argNames = "result")
    public void logResult(Object result) {
        // Result logging
    }
}

Integration with Standard Java

@AspectJ aspects are regular Java classes and can:

  • Use standard Java annotations alongside AspectJ annotations
  • Implement interfaces and extend classes
  • Be managed by dependency injection frameworks
  • Use standard Java compilation and tooling
@Aspect
@Component  // Spring annotation
@Transactional  // JPA annotation
public class IntegratedAspect {
    
    @Autowired
    private AuditService auditService;
    
    @PostConstruct
    public void initialize() {
        System.out.println("Aspect initialized");
    }
    
    @Before("@annotation(Audited)")
    public void auditOperation(JoinPoint joinPoint) {
        auditService.recordOperation(joinPoint.getSignature().getName());
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-aspectj--aspectjrt

docs

annotation-based-definition.md

aspect-management.md

index.md

join-point-introspection.md

reflection-api.md

runtime-utilities.md

signature-system.md

tile.json