or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

annotation-based-definition.mdaspect-management.mdindex.mdjoin-point-introspection.mdreflection-api.mdruntime-utilities.mdsignature-system.md

annotation-based-definition.mddocs/

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

```