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

core-abstractions.mddocs/

0

# Core AOP Abstractions

1

2

Fundamental interfaces and classes that form the foundation of Spring's AOP system. These abstractions provide the basic building blocks for implementing aspect-oriented programming, including pointcuts for defining where advice should be applied, advisors that combine advice with pointcuts, and various advice types for different interception strategies.

3

4

## Capabilities

5

6

### Pointcut System

7

8

Core abstraction for defining where advice should be applied, combining class filters and method matchers to precisely target join points.

9

10

```java { .api }

11

public interface Pointcut {

12

/**

13

* Return the ClassFilter for this pointcut.

14

* @return the ClassFilter (never null)

15

*/

16

ClassFilter getClassFilter();

17

18

/**

19

* Return the MethodMatcher for this pointcut.

20

* @return the MethodMatcher (never null)

21

*/

22

MethodMatcher getMethodMatcher();

23

24

/**

25

* Canonical Pointcut instance that always matches.

26

*/

27

Pointcut TRUE = TruePointcut.INSTANCE;

28

}

29

30

public interface ClassFilter {

31

/**

32

* Should the pointcut apply to the given interface or target class?

33

* @param clazz the candidate target class

34

* @return whether the advice should apply to the given target class

35

*/

36

boolean matches(Class<?> clazz);

37

38

/**

39

* Canonical ClassFilter instance that matches all classes.

40

*/

41

ClassFilter TRUE = TrueClassFilter.INSTANCE;

42

}

43

44

public interface MethodMatcher {

45

/**

46

* Perform static checking whether the given method matches.

47

* @param method the candidate method

48

* @param targetClass the target class

49

* @return whether or not this method matches statically

50

*/

51

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

52

53

/**

54

* Is this MethodMatcher dynamic, that is, must a final call be made on the

55

* {@link #matches(java.lang.reflect.Method, Class, Object[])} method at

56

* runtime even when the 2-arg matches method returns {@code true}?

57

* @return whether or not a runtime match via the 3-arg

58

* {@link #matches(java.lang.reflect.Method, Class, Object[])} method

59

* is required if static matching passed

60

*/

61

boolean isRuntime();

62

63

/**

64

* Check whether there a runtime (dynamic) match for this method,

65

* which must have matched statically.

66

* @param method the candidate method

67

* @param targetClass the target class

68

* @param args arguments to the method

69

* @return whether there's a runtime match

70

* @throws UnsupportedOperationException if matches does not implement

71

* the 3-arg method (i.e. if isRuntime() returns false)

72

*/

73

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

74

75

/**

76

* Canonical MethodMatcher instance that matches all methods.

77

*/

78

MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;

79

}

80

```

81

82

### Advisor Hierarchy

83

84

Advisors combine advice with applicability information to determine when and where advice should be applied.

85

86

```java { .api }

87

public interface Advisor {

88

/**

89

* Return the advice part of this aspect. An advice may be an

90

* interceptor, a before advice, a throws advice, etc.

91

* @return the advice that should apply if the pointcut matches

92

* @see org.aopalliance.intercept.MethodInterceptor

93

* @see BeforeAdvice

94

* @see ThrowsAdvice

95

* @see AfterReturningAdvice

96

*/

97

Advice getAdvice();

98

99

/**

100

* Return whether this advice is associated with a particular instance

101

* (for example, creating a mixin) or shared with all instances of

102

* the advised class obtained through the same Spring bean factory.

103

* <p><b>Note that this method is not currently used by the framework.</b>

104

* Typical Advisor implementations always return {@code true}.

105

* Use singleton/prototype bean definitions or appropriate programmatic

106

* proxy creation to ensure that Advisors have the correct lifecycle model.

107

* @return whether this advice is associated with a particular target instance

108

*/

109

boolean isPerInstance();

110

111

/**

112

* Common placeholder for an empty {@code Advice} to be preserved when

113

* no advice is applicable (e.g. from a {@code PointcutAdvisor} with a

114

* non-matching {@code Pointcut}).

115

*/

116

Advice EMPTY_ADVICE = new Advice() {};

117

}

118

119

public interface PointcutAdvisor extends Advisor {

120

/**

121

* Get the Pointcut that drives this advisor.

122

*/

123

Pointcut getPointcut();

124

}

125

126

public interface IntroductionAdvisor extends Advisor, IntroductionInfo {

127

/**

128

* Return the filter determining which target classes this introduction

129

* should apply to.

130

* <p>This represents the class part of a pointcut. Note that method

131

* matching doesn't make sense to introductions.

132

* @return the class filter

133

*/

134

ClassFilter getClassFilter();

135

136

/**

137

* Can the advised interfaces be implemented by the introduction advice?

138

* Invoked before adding an IntroductionAdvisor.

139

* @throws IllegalArgumentException if the advised interfaces can't be

140

* implemented by the introduction advice

141

*/

142

void validateInterfaces() throws IllegalArgumentException;

143

}

144

```

145

146

### Advice Type System

147

148

Base interfaces for different types of advice that can be applied at join points.

149

150

```java { .api }

151

public interface BeforeAdvice extends Advice {

152

// Marker interface for before advice

153

}

154

155

public interface AfterAdvice extends Advice {

156

// Marker interface for after advice

157

}

158

159

public interface MethodBeforeAdvice extends BeforeAdvice {

160

/**

161

* Callback before a given method is invoked.

162

* @param method the method being invoked

163

* @param args the arguments to the method

164

* @param target the target of the method invocation. May be {@code null}.

165

* @throws Throwable if this object wishes to abort the call.

166

* Any exception thrown will be returned to the caller if it's

167

* allowed by the method signature. Otherwise the exception

168

* will be wrapped as a runtime exception.

169

*/

170

void before(Method method, Object[] args, Object target) throws Throwable;

171

}

172

173

public interface AfterReturningAdvice extends AfterAdvice {

174

/**

175

* Callback after a given method successfully returns.

176

* @param returnValue the value returned by the method, if any

177

* @param method the method being invoked

178

* @param args the arguments to the method

179

* @param target the target of the method invocation. May be {@code null}.

180

* @throws Throwable if this object wishes to abort the call.

181

* Any exception thrown will be returned to the caller if it's

182

* allowed by the method signature. Otherwise the exception

183

* will be wrapped as a runtime exception.

184

*/

185

void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable;

186

}

187

188

public interface ThrowsAdvice extends AfterAdvice {

189

// Tag interface for throws advice

190

// Methods must follow pattern:

191

// void afterThrowing([Method, args, target], Exception ex)

192

}

193

```

194

195

### Introduction Support

196

197

Interfaces for implementing introductions (mixins) that add new interfaces to existing objects.

198

199

```java { .api }

200

public interface IntroductionInfo {

201

/**

202

* Return the additional interfaces introduced by this Advisor or Advice.

203

* @return the introduced interfaces

204

*/

205

Class<?>[] getInterfaces();

206

}

207

208

public interface IntroductionInterceptor extends MethodInterceptor, DynamicIntroductionAdvice {

209

// Combined interface for introduction interceptors

210

}

211

212

public interface DynamicIntroductionAdvice extends Advice {

213

/**

214

* Does this introduction advice implement the given interface?

215

* @param intf the interface to check

216

* @return whether the advice implements the specified interface

217

*/

218

boolean implementsInterface(Class<?> intf);

219

}

220

221

public interface IntroductionAwareMethodMatcher extends MethodMatcher {

222

/**

223

* Perform static checking whether the given method matches.

224

* This method is called when an AOP proxy is created, and need not

225

* account for the particular instance. If this method returns false

226

* or if the isRuntime() method returns false, no runtime check

227

* will be made.

228

* @param method the candidate method

229

* @param targetClass the target class

230

* @param hasIntroductions true if the object on whose behalf we are

231

* asking is the subject on one or more introductions; false otherwise

232

* @return whether or not this method matches statically

233

*/

234

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

235

}

236

```

237

238

### Proxy and Target Support

239

240

Core interfaces for working with AOP proxies and target objects.

241

242

```java { .api }

243

public interface TargetClassAware {

244

/**

245

* Return the target class behind the implementing object

246

* (typically a proxy configuration or an actual proxy).

247

* @return the target Class, or {@code null} if not known

248

*/

249

Class<?> getTargetClass();

250

}

251

252

public interface SpringProxy {

253

// Marker interface implemented by all proxies created by Spring's AOP infrastructure

254

}

255

256

public interface RawTargetAccess {

257

// Marker interface that indicates that the annotated method is eligible for

258

// invocation even if the target object is in "raw" mode

259

}

260

261

public interface ProxyMethodInvocation extends MethodInvocation {

262

/**

263

* Return the proxy that this method invocation was made through.

264

* @return the original proxy object

265

*/

266

Object getProxy();

267

268

/**

269

* Create a clone of this object. If cloning is done before {@code proceed()}

270

* is invoked on this object, {@code proceed()} can be invoked once per clone

271

* to invoke the joinpoint (and the rest of the advice chain) more than once.

272

* @return an invocable clone of this invocation.

273

* {@link #proceed()} can be called once per clone.

274

*/

275

MethodInvocation invocableClone();

276

277

/**

278

* Create a clone of this object. If cloning is done before {@code proceed()}

279

* is invoked on this object, {@code proceed()} can be invoked once per clone

280

* to invoke the joinpoint (and the rest of the advice chain) more than once.

281

* @param arguments the arguments that the cloned invocation is supposed to use,

282

* overriding the original arguments

283

* @return an invocable clone of this invocation.

284

* {@link #proceed()} can be called once per clone.

285

*/

286

MethodInvocation invocableClone(Object... arguments);

287

288

/**

289

* Set the arguments to be used on subsequent invocations in the any advice

290

* in this chain.

291

* @param arguments the argument array

292

*/

293

void setArguments(Object... arguments);

294

295

/**

296

* Add the specified user attribute with the given value to this invocation.

297

* <p>Such attributes are not used within the AOP framework itself.

298

* They are just kept as part of the invocation object, for use in

299

* special interceptors.

300

* @param key the name of the attribute

301

* @param value the value of the attribute, or {@code null} to reset it

302

*/

303

void setUserAttribute(String key, Object value);

304

305

/**

306

* Return the value of the specified user attribute.

307

* @param key the name of the attribute

308

* @return the value of the attribute, or {@code null} if not set

309

* @see #setUserAttribute

310

*/

311

Object getUserAttribute(String key);

312

}

313

```

314

315

## Usage Examples

316

317

### Creating Custom Pointcuts

318

319

```java

320

// Name-based pointcut

321

NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();

322

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

323

324

// Custom method matcher

325

MethodMatcher customMatcher = new MethodMatcher() {

326

@Override

327

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

328

return method.isAnnotationPresent(Transactional.class);

329

}

330

331

@Override

332

public boolean isRuntime() {

333

return false;

334

}

335

336

@Override

337

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

338

throw new UnsupportedOperationException("Not a runtime matcher");

339

}

340

};

341

342

// Composable pointcut

343

ComposablePointcut composite = new ComposablePointcut()

344

.union(pointcut)

345

.intersection(Pointcuts.forAnnotation(Service.class));

346

```

347

348

### Custom Advice Implementation

349

350

```java

351

public class LoggingBeforeAdvice implements MethodBeforeAdvice {

352

private static final Logger logger = LoggerFactory.getLogger(LoggingBeforeAdvice.class);

353

354

@Override

355

public void before(Method method, Object[] args, Object target) throws Throwable {

356

logger.info("Calling method: {} on target: {}",

357

method.getName(), target.getClass().getSimpleName());

358

}

359

}

360

361

public class CachingAfterReturningAdvice implements AfterReturningAdvice {

362

private final Map<String, Object> cache = new ConcurrentHashMap<>();

363

364

@Override

365

public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {

366

if (method.isAnnotationPresent(Cacheable.class)) {

367

String key = generateCacheKey(method, args);

368

cache.put(key, returnValue);

369

}

370

}

371

372

private String generateCacheKey(Method method, Object[] args) {

373

return method.getName() + Arrays.toString(args);

374

}

375

}

376

```

377

378

### AOP Utility Methods

379

380

Static utility methods for working with AOP proxies, target classes, and method detection.

381

382

```java { .api }

383

public abstract class AopUtils {

384

/**

385

* Check whether the given object is a AOP proxy.

386

* @param object the object to check

387

* @return whether the object is a AOP proxy

388

*/

389

public static boolean isAopProxy(@Nullable Object object);

390

391

/**

392

* Check whether the given object is a JDK dynamic proxy.

393

* @param object the object to check

394

* @return whether the object is a JDK dynamic proxy

395

*/

396

public static boolean isJdkDynamicProxy(@Nullable Object object);

397

398

/**

399

* Check whether the given object is a CGLIB proxy.

400

* @param object the object to check

401

* @return whether the object is a CGLIB proxy

402

*/

403

public static boolean isCglibProxy(@Nullable Object object);

404

405

/**

406

* Determine the target class of the given bean instance which might be an AOP proxy.

407

* @param candidate the instance to check (might be an AOP proxy)

408

* @return the target class (or the plain class of the given object as fallback)

409

*/

410

public static Class<?> getTargetClass(Object candidate);

411

412

/**

413

* Determine whether the given method is an "equals" method.

414

* @param method the method to check

415

* @return whether the method is an "equals" method

416

*/

417

public static boolean isEqualsMethod(@Nullable Method method);

418

419

/**

420

* Determine whether the given method is a "hashCode" method.

421

* @param method the method to check

422

* @return whether the method is a "hashCode" method

423

*/

424

public static boolean isHashCodeMethod(@Nullable Method method);

425

426

/**

427

* Determine whether the given method is a "toString" method.

428

* @param method the method to check

429

* @return whether the method is a "toString" method

430

*/

431

public static boolean isToStringMethod(@Nullable Method method);

432

433

/**

434

* Can the given pointcut apply at all on the given class?

435

* @param pc the static or dynamic pointcut to check

436

* @param targetClass the class to test

437

* @return whether the pointcut can apply on any method

438

*/

439

public static boolean canApply(Pointcut pc, Class<?> targetClass);

440

441

/**

442

* Can the given advisor apply at all on the given class?

443

* @param advisor the advisor to check

444

* @param targetClass class we're testing

445

* @return whether the pointcut can apply on any method

446

*/

447

public static boolean canApply(Advisor advisor, Class<?> targetClass);

448

}

449

```