Advice
Advice
Advices are the methods of an Aspect that are configured to stop at specific points in the program, identified by an advice type - a moment in the execution flow of the program, and a location in the code - known as "pointcuts".
Advice type
The advice type tells when the behavior of an aspect should be integrated. AspectJS supports the following Advice Types:
@Before
: runs the advice before the execution of the joinpoint.@Around
: wraps the advice around the execution of the joinpoint, allowing you to execute custom code before and after the join point, intercept arguments, or even skip the execution of the original joinpoint;@AfterReturn
: runs the advice after joinpoint completes without errors.@AfterThrow
: runs the advice after the joinpoint throws an error.@After
: runs the advice after the joinpoint returns or throws.
An advice is any method in an aspect class annotated with one of the above annotations.
@Aspect()
class ExampleAspect {
@Before(...)
exampleAdvice() {}
}
Pointcut
A pointcut is an expression that specifies the locations in a codebase where the aspect's behavior should be integrated.
warn Unlike AOP in other languages, AspectJS currenlty only supports pointcuts based on annotated elements.
Advices can be configured with several poincut at the same time:
import { AfterThrow, AfterThrowContext, Aspect, on } from '@aspectjs/core';
@Aspect()
export class LogErrorsAspect {
@AfterThrow(
on.classes.withAnnotations(LogErrors, Monitored),
on.methods.withAnnotations(LogErrors, Monitored),
)
logAround(context: AfterThrowContext, error: Error) {
console.error(
`${context.target}(${context.args.join(',')}) throwed error ${error}`,
);
// Propagate the error
throw error;
}
}
Advice context
Each advice is getting called with a context
passed as 1st argument, which holds the following details about execution context:
export interface AdviceContext {
/** The annotations context. Find all annotations on the current target **/
readonly annotations: BoundAnnotationFilter<ToAnnotationKind<T>>;
/** The 'this' instance bound to the current execution context **/
readonly instance: X;
/** the arguments originally passed to the joinpoint **/
readonly args: any[];
/** The location in the code targeted by this advice (class, method, property or parameter **/
readonly target: AdviceTarget<T, X>;
}
info The type of the advice context slightly varies with the type of the advice:
- Before: BeforeContext
- Around: AroundContext
- AfterReturn: AfterReturnContext
- AfterThrow: AfterThrowContext
- After: AfterContext