or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advice-interceptors.mdaspectj-integration.mdauto-proxy.mdcore-abstractions.mdindex.mdpointcuts.mdproxy-creation.mdtarget-sources.md

pointcuts.mddocs/

0

# Pointcut Implementations

1

2

Various pointcut implementations for different matching strategies including name-based, regular expression, annotation-based, and composable pointcuts. These implementations provide flexible ways to define where advice should be applied in your application, from simple method name patterns to complex AspectJ expressions.

3

4

## Capabilities

5

6

### Composable Pointcuts

7

8

Pointcut implementation that allows combining multiple pointcuts using union and intersection operations.

9

10

```java { .api }

11

public class ComposablePointcut implements Pointcut, Serializable {

12

/**

13

* Create a default ComposablePointcut, with {@code ClassFilter.TRUE}

14

* and {@code MethodMatcher.TRUE}.

15

*/

16

public ComposablePointcut();

17

18

/**

19

* Create a ComposablePointcut based on the given Pointcut.

20

* @param pointcut the original Pointcut

21

*/

22

public ComposablePointcut(Pointcut pointcut);

23

24

/**

25

* Create a ComposablePointcut for the given ClassFilter,

26

* with {@code MethodMatcher.TRUE}.

27

* @param classFilter the ClassFilter to use

28

*/

29

public ComposablePointcut(ClassFilter classFilter);

30

31

/**

32

* Create a ComposablePointcut for the given MethodMatcher,

33

* with {@code ClassFilter.TRUE}.

34

* @param methodMatcher the MethodMatcher to use

35

*/

36

public ComposablePointcut(MethodMatcher methodMatcher);

37

38

/**

39

* Create a ComposablePointcut for the given ClassFilter and MethodMatcher.

40

* @param classFilter the ClassFilter to use

41

* @param methodMatcher the MethodMatcher to use

42

*/

43

public ComposablePointcut(ClassFilter classFilter, MethodMatcher methodMatcher);

44

45

/**

46

* Apply a union with the given Pointcut.

47

* @param other the Pointcut to apply a union with

48

* @return this composable pointcut (for call chaining)

49

*/

50

public ComposablePointcut union(Pointcut other);

51

52

/**

53

* Apply an intersection with the given Pointcut.

54

* @param other the Pointcut to apply an intersection with

55

* @return this composable pointcut (for call chaining)

56

*/

57

public ComposablePointcut intersection(Pointcut other);

58

59

/**

60

* Apply a union with the given ClassFilter.

61

* @param other the ClassFilter to apply a union with

62

* @return this composable pointcut (for call chaining)

63

*/

64

public ComposablePointcut union(ClassFilter other);

65

66

/**

67

* Apply an intersection with the given ClassFilter.

68

* @param other the ClassFilter to apply an intersection with

69

* @return this composable pointcut (for call chaining)

70

*/

71

public ComposablePointcut intersection(ClassFilter other);

72

73

/**

74

* Apply a union with the given MethodMatcher.

75

* @param other the MethodMatcher to apply a union with

76

* @return this composable pointcut (for call chaining)

77

*/

78

public ComposablePointcut union(MethodMatcher other);

79

80

/**

81

* Apply an intersection with the given MethodMatcher.

82

* @param other the MethodMatcher to apply an intersection with

83

* @return this composable pointcut (for call chaining)

84

*/

85

public ComposablePointcut intersection(MethodMatcher other);

86

87

@Override

88

public ClassFilter getClassFilter();

89

90

@Override

91

public MethodMatcher getMethodMatcher();

92

}

93

```

94

95

### Name-Based Pointcuts

96

97

Pointcut implementations that match methods based on method names or patterns.

98

99

```java { .api }

100

public class NameMatchMethodPointcut extends StaticMethodMatcherPointcut implements Serializable {

101

/**

102

* Convenience method when we have only a single method name to match.

103

* Use either this method or {@code setMappedNames}, not both.

104

* @param mappedName the name of the method to match

105

* @see #setMappedNames

106

*/

107

public void setMappedName(String mappedName);

108

109

/**

110

* Set the method names defining methods to match.

111

* Matching will be the union of all these; if any match, the pointcut matches.

112

* @param mappedNames the method names to match

113

*/

114

public void setMappedNames(String... mappedNames);

115

116

/**

117

* Add another eligible method name, in addition to those already named.

118

* Like the set methods, this method is for use when configuring proxies,

119

* before a proxy is used.

120

* <p><b>NB:</b> This method does not work after the proxy is in

121

* use, as advice chains will be cached.

122

* @param name name of the additional method that will match

123

* @return this pointcut to allow for multiple additions in one line

124

*/

125

public NameMatchMethodPointcut addMethodName(String name);

126

127

@Override

128

public boolean matches(Method method, Class<?> targetClass);

129

130

@Override

131

public boolean equals(Object other);

132

133

@Override

134

public int hashCode();

135

}

136

```

137

138

### Regular Expression Pointcuts

139

140

Pointcut implementations using regular expressions for method matching.

141

142

```java { .api }

143

public abstract class AbstractRegexpMethodPointcut extends StaticMethodMatcherPointcut implements Serializable {

144

/**

145

* Convenience method when we have only a single pattern.

146

* Use either this method or {@code setPatterns}, not both.

147

* @param pattern the pattern to match

148

* @see #setPatterns

149

*/

150

public void setPattern(String pattern);

151

152

/**

153

* Set the regular expressions defining methods to match.

154

* Matching will be the union of all these; if any match, the pointcut matches.

155

* @param patterns the patterns to match

156

*/

157

public void setPatterns(String... patterns);

158

159

/**

160

* Return the regular expressions for method matching.

161

*/

162

public String[] getPatterns();

163

164

/**

165

* Try to match the regular expression against the fully qualified name

166

* of the target class as well as against the method's declaring class.

167

*/

168

@Override

169

public boolean matches(Method method, Class<?> targetClass);

170

171

/**

172

* Subclasses must implement this to initialize regex pointcuts.

173

* Can be invoked multiple times.

174

* <p>This method will be invoked from the {@code setPatterns} method,

175

* and also on deserialization.

176

* @param patterns the patterns to initialize

177

* @throws IllegalArgumentException in case of an invalid pattern

178

*/

179

protected abstract void initPatternRepresentation(String[] patterns) throws IllegalArgumentException;

180

181

/**

182

* Does the pattern at the given index match the given String?

183

* @param patternIndex the index of the pattern to match against

184

* @param str the String to match

185

* @return whether there's a match

186

*/

187

protected abstract boolean matches(String pattern, int patternIndex);

188

}

189

190

public class JdkRegexpMethodPointcut extends AbstractRegexpMethodPointcut {

191

/**

192

* Internal method to initialize the {@code Pattern} representation of the pointcut.

193

*/

194

@Override

195

protected void initPatternRepresentation(String[] patterns) throws PatternSyntaxException;

196

197

/**

198

* Does the pattern at the given index match this string?

199

*/

200

@Override

201

protected boolean matches(String pattern, int patternIndex);

202

}

203

```

204

205

### Control Flow Pointcuts

206

207

Pointcut that matches methods executing under a specific control flow.

208

209

```java { .api }

210

public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher, Serializable {

211

/**

212

* Construct a new pointcut that matches all methods executing

213

* under a class with the given name, in any package.

214

* @param clazz the clazz

215

*/

216

public ControlFlowPointcut(Class<?> clazz);

217

218

/**

219

* Construct a new pointcut that matches all methods executing

220

* under a class with the given name, in any package.

221

* @param clazz the clazz

222

* @param methodName the name of the method (may be {@code null})

223

*/

224

public ControlFlowPointcut(Class<?> clazz, String methodName);

225

226

/**

227

* Subclasses can override this for greater filtering (and performance).

228

*/

229

@Override

230

public boolean matches(Class<?> clazz);

231

232

/**

233

* Subclasses can override this if it's possible to filter out

234

* some candidate classes.

235

*/

236

@Override

237

public boolean matches(Method method, Class<?> targetClass);

238

239

@Override

240

public boolean isRuntime();

241

242

@Override

243

public boolean matches(Method method, Class<?> targetClass, Object... args);

244

245

@Override

246

public ClassFilter getClassFilter();

247

248

@Override

249

public MethodMatcher getMethodMatcher();

250

}

251

```

252

253

### Annotation-Based Pointcuts

254

255

Pointcut implementations that match based on annotations present on classes or methods.

256

257

```java { .api }

258

public class AnnotationMatchingPointcut implements Pointcut {

259

/**

260

* Create a new AnnotationMatchingPointcut for which both the class and method

261

* annotations will be checked.

262

* @param classAnnotationType the annotation type to check at the class level

263

* (can be {@code null})

264

* @param methodAnnotationType the annotation type to check at the method level

265

* (can be {@code null})

266

*/

267

public AnnotationMatchingPointcut(Class<? extends Annotation> classAnnotationType,

268

Class<? extends Annotation> methodAnnotationType);

269

270

/**

271

* Create a new AnnotationMatchingPointcut for the given annotation type.

272

* @param classAnnotationType the annotation type to check at the class level

273

* @param checkInherited whether to explicitly check the superclasses and

274

* interfaces for the annotation type as well (even if the annotation type

275

* is not marked as inherited itself)

276

*/

277

public AnnotationMatchingPointcut(Class<? extends Annotation> classAnnotationType, boolean checkInherited);

278

279

/**

280

* Factory method for an AnnotationMatchingPointcut that matches

281

* all methods carrying the specified annotation at the class level.

282

* @param annotationType the annotation type to check at the class level

283

* @return the corresponding AnnotationMatchingPointcut

284

*/

285

public static AnnotationMatchingPointcut forClassAnnotation(Class<? extends Annotation> annotationType);

286

287

/**

288

* Factory method for an AnnotationMatchingPointcut that matches

289

* all methods carrying the specified annotation at the method level.

290

* @param annotationType the annotation type to check at the method level

291

* @return the corresponding AnnotationMatchingPointcut

292

*/

293

public static AnnotationMatchingPointcut forMethodAnnotation(Class<? extends Annotation> annotationType);

294

295

@Override

296

public ClassFilter getClassFilter();

297

298

@Override

299

public MethodMatcher getMethodMatcher();

300

}

301

302

public class AnnotationClassFilter implements ClassFilter {

303

/**

304

* Create a new AnnotationClassFilter for the given annotation type.

305

* @param annotationType the annotation type to look for

306

*/

307

public AnnotationClassFilter(Class<? extends Annotation> annotationType);

308

309

/**

310

* Create a new AnnotationClassFilter for the given annotation type.

311

* @param annotationType the annotation type to look for

312

* @param checkInherited whether to explicitly check the superclasses and

313

* interfaces for the annotation type as well (even if the annotation type

314

* is not marked as inherited itself)

315

*/

316

public AnnotationClassFilter(Class<? extends Annotation> annotationType, boolean checkInherited);

317

318

@Override

319

public boolean matches(Class<?> clazz);

320

}

321

322

public class AnnotationMethodMatcher extends StaticMethodMatcher {

323

/**

324

* Create a new AnnotationMethodMatcher for the given annotation type.

325

* @param annotationType the annotation type to look for

326

*/

327

public AnnotationMethodMatcher(Class<? extends Annotation> annotationType);

328

329

/**

330

* Create a new AnnotationMethodMatcher for the given annotation type.

331

* @param annotationType the annotation type to look for

332

* @param checkInherited whether to explicitly check the superclasses and

333

* interfaces for the annotation type as well (even if the annotation type

334

* is not marked as inherited itself)

335

*/

336

public AnnotationMethodMatcher(Class<? extends Annotation> annotationType, boolean checkInherited);

337

338

@Override

339

public boolean matches(Method method, Class<?> targetClass);

340

}

341

```

342

343

### Static Method Matcher Base Classes

344

345

Base classes for implementing static method matchers (no runtime checks needed).

346

347

```java { .api }

348

public abstract class StaticMethodMatcher implements MethodMatcher {

349

@Override

350

public final boolean isRuntime();

351

352

@Override

353

public final boolean matches(Method method, Class<?> targetClass, Object... args);

354

355

/**

356

* Subclasses must implement this to return {@code true} if the method

357

* matches. Note that there will be no runtime check (i.e. no check on the

358

* method's arguments) if this method returns {@code false}.

359

* @param method the candidate method

360

* @param targetClass target class (may be {@code null}, in which case

361

* the candidate class must be taken to be the method's declaring class)

362

* @return whether or not this method matches statically

363

*/

364

public abstract boolean matches(Method method, Class<?> targetClass);

365

}

366

367

public abstract class StaticMethodMatcherPointcut extends StaticMethodMatcher implements Pointcut {

368

/**

369

* Set the {@link ClassFilter} to use for this pointcut.

370

* Default is {@link ClassFilter#TRUE}.

371

*/

372

public void setClassFilter(ClassFilter classFilter);

373

374

@Override

375

public ClassFilter getClassFilter();

376

377

@Override

378

public final MethodMatcher getMethodMatcher();

379

}

380

381

public abstract class DynamicMethodMatcher implements MethodMatcher {

382

@Override

383

public final boolean isRuntime();

384

385

/**

386

* Can override to add preconditions for dynamic matching. This implementation

387

* always returns true.

388

*/

389

@Override

390

public boolean matches(Method method, Class<?> targetClass);

391

392

/**

393

* Must override to implement runtime matching.

394

* The result of the 2-parameter {@link #matches(Method, Class)} method

395

* is taken into account for static matching checks already.

396

* @param method the candidate method

397

* @param targetClass the target class

398

* @param args arguments to the method

399

* @return whether there's a runtime match

400

*/

401

public abstract boolean matches(Method method, Class<?> targetClass, Object... args);

402

}

403

404

public abstract class DynamicMethodMatcherPointcut extends DynamicMethodMatcher implements Pointcut {

405

/**

406

* Set the {@link ClassFilter} to use for this pointcut.

407

* Default is {@link ClassFilter#TRUE}.

408

*/

409

public void setClassFilter(ClassFilter classFilter);

410

411

@Override

412

public ClassFilter getClassFilter();

413

414

@Override

415

public final MethodMatcher getMethodMatcher();

416

}

417

```

418

419

### Utility Classes

420

421

Utility classes providing static methods for working with pointcuts, class filters, and method matchers.

422

423

```java { .api }

424

public abstract class Pointcuts {

425

/**

426

* Match all methods that <i>either</i> (or both) of the given pointcuts matches.

427

* @param pc1 the first Pointcut

428

* @param pc2 the second Pointcut

429

* @return a distinct Pointcut that matches all methods that either

430

* of the given Pointcuts matches

431

*/

432

public static Pointcut union(Pointcut pc1, Pointcut pc2);

433

434

/**

435

* Match all methods that <i>both</i> the given pointcuts match.

436

* @param pc1 the first Pointcut

437

* @param pc2 the second Pointcut

438

* @return a distinct Pointcut that matches all methods that both

439

* of the given Pointcuts match

440

*/

441

public static Pointcut intersection(Pointcut pc1, Pointcut pc2);

442

443

/**

444

* Perform the least expensive check for a pointcut match.

445

* @param pointcut the pointcut to match

446

* @param method the candidate method

447

* @param targetClass the target class

448

* @param args arguments to the method

449

* @return whether there's a runtime match

450

*/

451

public static boolean matches(Pointcut pointcut, Method method, Class<?> targetClass, Object... args);

452

}

453

454

public abstract class ClassFilters {

455

/**

456

* Match all classes that <i>either</i> (or both) of the given ClassFilters matches.

457

* @param cf1 the first ClassFilter

458

* @param cf2 the second ClassFilter

459

* @return a distinct ClassFilter that matches all classes that either

460

* of the given ClassFilter matches

461

*/

462

public static ClassFilter union(ClassFilter cf1, ClassFilter cf2);

463

464

/**

465

* Match all classes that <i>both</i> the given ClassFilters match.

466

* @param cf1 the first ClassFilter

467

* @param cf2 the second ClassFilter

468

* @return a distinct ClassFilter that matches all classes that both

469

* of the given ClassFilters match

470

*/

471

public static ClassFilter intersection(ClassFilter cf1, ClassFilter cf2);

472

}

473

474

public abstract class MethodMatchers {

475

/**

476

* Match all methods that <i>either</i> (or both) of the given MethodMatchers matches.

477

* @param mm1 the first MethodMatcher

478

* @param mm2 the second MethodMatcher

479

* @return a distinct MethodMatcher that matches all methods that either

480

* of the given MethodMatchers matches

481

*/

482

public static MethodMatcher union(MethodMatcher mm1, MethodMatcher mm2);

483

484

/**

485

* Match all methods that <i>both</i> the given MethodMatchers match.

486

* @param mm1 the first MethodMatcher

487

* @param mm2 the second MethodMatcher

488

* @return a distinct MethodMatcher that matches all methods that both

489

* of the given MethodMatchers match

490

*/

491

public static MethodMatcher intersection(MethodMatcher mm1, MethodMatcher mm2);

492

}

493

```

494

495

### Expression Pointcuts

496

497

Interface for pointcuts that use string expressions for definition.

498

499

```java { .api }

500

public interface ExpressionPointcut {

501

/**

502

* Return the String expression for this pointcut.

503

* @return the String expression

504

*/

505

String getExpression();

506

}

507

```

508

509

## Usage Examples

510

511

### Creating Composable Pointcuts

512

513

```java

514

// Start with a basic name-based pointcut

515

NameMatchMethodPointcut namePointcut = new NameMatchMethodPointcut();

516

namePointcut.setMappedNames("save*", "update*", "delete*");

517

518

// Create annotation-based pointcut

519

AnnotationMatchingPointcut annotationPointcut =

520

AnnotationMatchingPointcut.forMethodAnnotation(Transactional.class);

521

522

// Combine them using union

523

ComposablePointcut composablePointcut = new ComposablePointcut(namePointcut)

524

.union(annotationPointcut);

525

526

// Add class filter to restrict to service classes

527

ClassFilter serviceFilter = new AnnotationClassFilter(Service.class);

528

composablePointcut.intersection(serviceFilter);

529

530

// Create advisor with composed pointcut

531

DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(

532

composablePointcut,

533

new LoggingInterceptor()

534

);

535

```

536

537

### Regular Expression Pointcuts

538

539

```java

540

// Create regex pointcut for service layer methods

541

JdkRegexpMethodPointcut regexPointcut = new JdkRegexpMethodPointcut();

542

regexPointcut.setPatterns(

543

".*\\.service\\..*Service\\..*",

544

".*\\.repository\\..*Repository\\.find.*",

545

".*\\.dao\\..*Dao\\.get.*"

546

);

547

548

// Use in advisor

549

DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(

550

regexPointcut,

551

new PerformanceMonitorInterceptor()

552

);

553

```

554

555

### Control Flow Pointcuts

556

557

```java

558

// Match methods called from specific control flow

559

ControlFlowPointcut controlFlowPointcut = new ControlFlowPointcut(

560

UserController.class,

561

"handleRequest"

562

);

563

564

// All methods called during UserController.handleRequest() execution

565

DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(

566

controlFlowPointcut,

567

new SecurityInterceptor()

568

);

569

```

570

571

### Dynamic Method Matchers

572

573

```java

574

// Custom dynamic matcher based on method parameters

575

DynamicMethodMatcher dynamicMatcher = new DynamicMethodMatcher() {

576

@Override

577

public boolean matches(Method method, Class<?> targetClass) {

578

// Static check: method must have parameters

579

return method.getParameterCount() > 0;

580

}

581

582

@Override

583

public boolean matches(Method method, Class<?> targetClass, Object... args) {

584

// Dynamic check: first parameter must be non-null String

585

return args.length > 0 &&

586

args[0] instanceof String &&

587

args[0] != null;

588

}

589

};

590

591

// Convert to pointcut

592

DynamicMethodMatcherPointcut dynamicPointcut = new DynamicMethodMatcherPointcut() {

593

@Override

594

public boolean matches(Method method, Class<?> targetClass) {

595

return dynamicMatcher.matches(method, targetClass);

596

}

597

598

@Override

599

public boolean matches(Method method, Class<?> targetClass, Object... args) {

600

return dynamicMatcher.matches(method, targetClass, args);

601

}

602

};

603

```

604

605

### Custom Static Method Matcher

606

607

```java

608

// Match methods with specific return type

609

public class ReturnTypeMethodMatcher extends StaticMethodMatcher {

610

private final Class<?> expectedReturnType;

611

612

public ReturnTypeMethodMatcher(Class<?> expectedReturnType) {

613

this.expectedReturnType = expectedReturnType;

614

}

615

616

@Override

617

public boolean matches(Method method, Class<?> targetClass) {

618

return expectedReturnType.isAssignableFrom(method.getReturnType());

619

}

620

}

621

622

// Use the custom matcher

623

ReturnTypeMethodMatcher stringReturnMatcher = new ReturnTypeMethodMatcher(String.class);

624

StaticMethodMatcherPointcut pointcut = new StaticMethodMatcherPointcut() {

625

@Override

626

public boolean matches(Method method, Class<?> targetClass) {

627

return stringReturnMatcher.matches(method, targetClass);

628

}

629

};

630

```

631

632

### Combining Multiple Filters

633

634

```java

635

// Create complex pointcut using utility methods

636

ClassFilter serviceOrController = ClassFilters.union(

637

new AnnotationClassFilter(Service.class),

638

new AnnotationClassFilter(Controller.class)

639

);

640

641

MethodMatcher publicMethods = new MethodMatcher() {

642

@Override

643

public boolean matches(Method method, Class<?> targetClass) {

644

return Modifier.isPublic(method.getModifiers());

645

}

646

647

@Override

648

public boolean isRuntime() {

649

return false;

650

}

651

652

@Override

653

public boolean matches(Method method, Class<?> targetClass, Object... args) {

654

throw new UnsupportedOperationException();

655

}

656

};

657

658

MethodMatcher nonGetterMethods = new StaticMethodMatcher() {

659

@Override

660

public boolean matches(Method method, Class<?> targetClass) {

661

return !method.getName().startsWith("get") &&

662

!method.getName().startsWith("is");

663

}

664

};

665

666

MethodMatcher combinedMethodMatcher = MethodMatchers.intersection(

667

publicMethods,

668

nonGetterMethods

669

);

670

671

// Create final pointcut

672

ComposablePointcut finalPointcut = new ComposablePointcut(

673

serviceOrController,

674

combinedMethodMatcher

675

);

676

```