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

proxy-creation.mddocs/

0

# Proxy Creation and Management

1

2

ProxyFactory and related classes provide programmatic creation of AOP proxies with comprehensive configuration options for different proxy strategies, target source management, and advisor chains. This system enables flexible runtime proxy creation for both interface-based and class-based proxying scenarios.

3

4

## Capabilities

5

6

### ProxyFactory - Main Entry Point

7

8

The primary class for creating AOP proxies programmatically, providing fluent configuration and multiple creation strategies.

9

10

```java { .api }

11

public class ProxyFactory extends ProxyCreatorSupport {

12

/**

13

* Create a new ProxyFactory.

14

*/

15

public ProxyFactory();

16

17

/**

18

* Create a new ProxyFactory.

19

* Will proxy all interfaces that the given target implements.

20

* @param target the target object to be proxied

21

*/

22

public ProxyFactory(Object target);

23

24

/**

25

* Create a new ProxyFactory.

26

* No target, only interfaces. Must add interceptors.

27

* @param proxyInterfaces the interfaces that the proxy should implement

28

*/

29

public ProxyFactory(Class<?>... proxyInterfaces);

30

31

/**

32

* Create a new ProxyFactory for the given interface and interceptor.

33

* Convenience method for creating a proxy for a single interceptor,

34

* assuming that the interceptor handles all calls itself rather than

35

* delegating to a target, like in the case of remoting proxies.

36

* @param proxyInterface the interface that the proxy should implement

37

* @param interceptor the interceptor that the proxy should invoke

38

*/

39

public ProxyFactory(Class<?> proxyInterface, Interceptor interceptor);

40

41

/**

42

* Create a ProxyFactory for the specified {@code TargetSource}.

43

* @param proxyInterface the interface that the proxy should implement

44

* @param targetSource the source for the target object to be proxied

45

*/

46

public ProxyFactory(Class<?> proxyInterface, TargetSource targetSource);

47

48

/**

49

* Create a proxy according to this factory's settings.

50

* <p>Can be called repeatedly. Effect will vary if we've added

51

* or removed interfaces. Can add and remove interceptors.

52

* <p>Uses the default class loader: usually, the thread context class loader

53

* (if necessary for proxy creation).

54

* @return the proxy object

55

*/

56

public Object getProxy();

57

58

/**

59

* Create a proxy according to this factory's settings.

60

* <p>Uses the given class loader (if necessary for proxy creation).

61

* @param classLoader the class loader to create the proxy with

62

* (or {@code null} for the low-level proxy facility's default)

63

* @return the proxy object

64

*/

65

public Object getProxy(ClassLoader classLoader);

66

67

/**

68

* Determine the proxy class according to this factory's settings.

69

* <p>Uses the default class loader: usually, the thread context class loader

70

* (if necessary for proxy creation).

71

* @return the proxy class

72

*/

73

public Class<?> getProxyClass();

74

75

/**

76

* Determine the proxy class according to this factory's settings.

77

* <p>Uses the given class loader (if necessary for proxy creation).

78

* @param classLoader the class loader to create the proxy with

79

* (or {@code null} for the low-level proxy facility's default)

80

* @return the proxy class

81

*/

82

public Class<?> getProxyClass(ClassLoader classLoader);

83

84

// Static convenience methods

85

86

/**

87

* Create a proxy for the specified {@code TargetSource}.

88

* @param targetSource the source for the target object to be proxied

89

* @return the proxy object

90

*/

91

public static Object getProxy(TargetSource targetSource);

92

93

/**

94

* Create a proxy for the specified {@code TargetSource},

95

* using the given class loader.

96

* @param targetSource the source for the target object to be proxied

97

* @param classLoader the class loader to use for the proxy

98

* @return the proxy object

99

*/

100

public static Object getProxy(TargetSource targetSource, ClassLoader classLoader);

101

102

/**

103

* Create a proxy for the given interface and interceptor.

104

* @param proxyInterface the interface that the proxy should implement

105

* @param interceptor the interceptor that the proxy should invoke

106

* @return the proxy object

107

*/

108

public static <T> T getProxy(Class<T> proxyInterface, Interceptor interceptor);

109

110

/**

111

* Create a proxy for the specified {@code TargetSource} that extends

112

* the target class of the {@code TargetSource}.

113

* @param proxyInterface the interface that the proxy should implement

114

* @param targetSource the {@code TargetSource} the proxy should delegate to

115

* @return the proxy object

116

*/

117

public static <T> T getProxy(Class<T> proxyInterface, TargetSource targetSource);

118

}

119

```

120

121

### ProxyCreatorSupport - Base Class

122

123

Base class for proxy factories, providing common functionality for AOP proxy creation and configuration.

124

125

```java { .api }

126

public class ProxyCreatorSupport extends AdvisedSupport {

127

/**

128

* Set the AopProxyFactory to use.

129

* <p>Default is {@link DefaultAopProxyFactory}, creating either a CGLIB proxy

130

* or a JDK dynamic proxy.

131

* @param aopProxyFactory the AOP proxy factory to use

132

*/

133

public void setAopProxyFactory(AopProxyFactory aopProxyFactory);

134

135

/**

136

* Return the AopProxyFactory that this ProxyConfig uses.

137

*/

138

public AopProxyFactory getAopProxyFactory();

139

140

/**

141

* Call this method on a new instance created by the no-arg constructor

142

* to create an independent copy of the configuration from the given object.

143

* @param other the AdvisedSupport object to copy configuration from

144

*/

145

public void copyConfigurationFrom(AdvisedSupport other);

146

147

/**

148

* Create an AOP proxy for this configuration.

149

* @return the AOP proxy for this configuration

150

* @throws AopConfigException if the configuration is invalid

151

*/

152

protected final synchronized AopProxy createAopProxy();

153

154

/**

155

* Copy configuration from the other config object.

156

* @param other configuration to copy from

157

*/

158

protected void copyConfigurationFrom(AdvisedSupport other, TargetSource targetSource, List<Advisor> advisors);

159

}

160

```

161

162

### AOP Proxy Factory System

163

164

Factory interfaces and implementations for creating different types of AOP proxies.

165

166

```java { .api }

167

public interface AopProxyFactory {

168

/**

169

* Create an {@link AopProxy} for the given AOP configuration.

170

* @param config the AOP configuration in the form of an

171

* AdvisedSupport object

172

* @return the corresponding AOP proxy

173

* @throws AopConfigException if the configuration is invalid

174

*/

175

AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;

176

}

177

178

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

179

@Override

180

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;

181

}

182

183

public interface AopProxy {

184

/**

185

* Create a new proxy object.

186

* <p>Uses AopProxy's default class loader (if necessary for proxy creation):

187

* usually, the thread context class loader.

188

* @return the new proxy object (never {@code null})

189

* @see Thread#getContextClassLoader()

190

*/

191

Object getProxy();

192

193

/**

194

* Create a new proxy object.

195

* <p>Uses the given class loader (if necessary for proxy creation).

196

* {@code null} will simply be passed down and thus lead to the low-level

197

* proxy facility's default, which is usually different from the default

198

* chosen by the AopProxy implementation's {@link #getProxy()} method.

199

* @param classLoader the class loader to create the proxy with

200

* (or {@code null} for the low-level proxy facility's default)

201

* @return the new proxy object (never {@code null})

202

*/

203

Object getProxy(ClassLoader classLoader);

204

205

/**

206

* Return the proxy class, as opposed to the proxy instance.

207

* <p>This is essentially equivalent to {@code getProxy().getClass()}

208

* but more efficient (no proxy instantiation required).

209

* @param classLoader the class loader to determine the proxy class for

210

* (may be {@code null} to prioritize the AopProxy implementation's

211

* chosen default class loader)

212

* @return the proxy class (never {@code null})

213

*/

214

Class<?> getProxyClass(ClassLoader classLoader);

215

}

216

```

217

218

### Proxy Configuration Support

219

220

Configuration classes and interfaces for managing AOP proxy settings.

221

222

```java { .api }

223

public class ProxyConfig implements Serializable {

224

/**

225

* Set whether to proxy the target class directly, instead of just proxying

226

* specific interfaces. Default is "false".

227

* <p>Set this to "true" to force proxying for the TargetSource's exposed

228

* target class. If that target class is an interface, a JDK proxy will be

229

* created for the given interface. If that target class is any other class,

230

* a CGLIB proxy will be created for the given class.

231

* @param proxyTargetClass whether to proxy the target class directly as well

232

*/

233

public void setProxyTargetClass(boolean proxyTargetClass);

234

235

/**

236

* Return whether the proxy should be cast to advised.

237

*/

238

public boolean isProxyTargetClass();

239

240

/**

241

* Set whether proxies should perform aggressive optimizations.

242

* The exact meaning of "aggressive optimizations" will differ

243

* between proxies, but there is usually some tradeoff.

244

* Default is "false".

245

* @param optimize whether to apply aggressive optimizations

246

*/

247

public void setOptimize(boolean optimize);

248

249

/**

250

* Return whether proxies should perform aggressive optimizations.

251

*/

252

public boolean isOptimize();

253

254

/**

255

* Set whether this config should be frozen.

256

* <p>When a config is frozen, no advice changes can be made. This is

257

* useful for optimization, and useful when we don't want callers to

258

* be able to manipulate configuration after casting to Advised.

259

* @param frozen whether configuration should be frozen

260

*/

261

public void setFrozen(boolean frozen);

262

263

/**

264

* Return whether the config is frozen, and no advice changes can be made.

265

*/

266

public boolean isFrozen();

267

268

/**

269

* Set whether the proxy created by this configuration should be exposed

270

* via the {@link AopContext} so that it can be accessed by the target.

271

* <p>Default is "false", meaning that no guarantees are made that the target

272

* will be able to access the proxy. If this is set to "true", the proxy

273

* will be accessible via {@link AopContext#currentProxy()}, provided that

274

* the AopContext is configured to hold it.

275

* @param exposeProxy whether to expose the proxy in the AopContext

276

*/

277

public void setExposeProxy(boolean exposeProxy);

278

279

/**

280

* Return whether the factory should expose the proxy.

281

*/

282

public boolean isExposeProxy();

283

284

/**

285

* Set whether this proxy configuration is pre-filtered so that it only

286

* contains applicable advisors (matching this proxy's target class).

287

* <p>Default is "false". Set this to "true" if the advisors have been

288

* pre-filtered already, meaning that the ClassFilter check can be skipped

289

* when building the actual advisor chain for proxy invocations.

290

* @param preFiltered whether the proxy is pre-filtered

291

* @see ClassFilter

292

*/

293

public void setPreFiltered(boolean preFiltered);

294

295

/**

296

* Return whether this proxy configuration is pre-filtered so that it only

297

* contains applicable advisors (matching this proxy's target class).

298

*/

299

public boolean isPreFiltered();

300

}

301

302

public interface Advised extends TargetClassAware {

303

/**

304

* Return whether the Advised configuration is frozen,

305

* in which case no advice changes can be made.

306

*/

307

boolean isFrozen();

308

309

/**

310

* Are we proxying the full target class instead of specified interfaces?

311

*/

312

boolean isProxyTargetClass();

313

314

/**

315

* Return the interfaces proxied by the AOP proxy.

316

* <p>Will not include the target class, which may also be proxied.

317

*/

318

Class<?>[] getProxiedInterfaces();

319

320

/**

321

* Determine whether the given interface is proxied.

322

* @param intf the interface to check

323

*/

324

boolean isInterfaceProxied(Class<?> intf);

325

326

/**

327

* Change the {@code TargetSource} used by this {@code Advised} object.

328

* Only works if the configuration isn't {@linkplain #isFrozen frozen}.

329

* @param targetSource new TargetSource to use

330

*/

331

void setTargetSource(TargetSource targetSource);

332

333

/**

334

* Return the {@code TargetSource} used by this {@code Advised} object.

335

*/

336

TargetSource getTargetSource();

337

338

/**

339

* Set whether the proxy should be exposed by the AOP framework as a

340

* {@link ThreadLocal} for retrieval via the {@link AopContext} class.

341

* <p>It can be necessary to expose proxy if an advised object needs

342

* to call another advised method on itself. (If it uses {@code this},

343

* the call will not be advised).

344

* <p>Default is "false", for optimal performance.

345

*/

346

void setExposeProxy(boolean exposeProxy);

347

348

/**

349

* Return whether the factory should expose the proxy as a ThreadLocal

350

* to be retrievable via the AopContext class. This is particularly

351

* useful if an advised object needs to call another advised method on itself.

352

*/

353

boolean isExposeProxy();

354

355

/**

356

* Set whether this proxy configuration is pre-filtered so that it only

357

* contains applicable advisors (matching this proxy's target class).

358

* <p>Default is "false". Set this to "true" if the advisors have been

359

* pre-filtered already, meaning that the ClassFilter check can be skipped

360

* when building the actual advisor chain for proxy invocations.

361

* @param preFiltered whether the proxy is pre-filtered

362

*/

363

void setPreFiltered(boolean preFiltered);

364

365

/**

366

* Return whether this proxy configuration is pre-filtered so that it only

367

* contains applicable advisors (matching this proxy's target class).

368

*/

369

boolean isPreFiltered();

370

371

/**

372

* Return the advisors applying to this proxy.

373

* @return a list of Advisors applying to this proxy (never {@code null})

374

*/

375

Advisor[] getAdvisors();

376

377

/**

378

* Add an advisor at the end of the advisor chain.

379

* <p>The Advisor may be an {@link org.springframework.aop.IntroductionAdvisor},

380

* in which case the advised interfaces will be those supported by the advisor.

381

* @param advisor the advisor to add to the end of the chain

382

* @throws AopConfigException in case of invalid advice

383

*/

384

void addAdvisor(Advisor advisor) throws AopConfigException;

385

386

/**

387

* Add an Advisor at the specified position in the chain.

388

* @param pos position in chain (0 is head). Must be valid.

389

* @param advisor advisor to add at the specified position in the chain

390

* @throws AopConfigException in case of invalid advice

391

*/

392

void addAdvisor(int pos, Advisor advisor) throws AopConfigException;

393

394

/**

395

* Remove the given advisor.

396

* @param advisor the advisor to remove

397

* @return {@code true} if the advisor was removed; {@code false}

398

* if the advisor was not found in the list

399

*/

400

boolean removeAdvisor(Advisor advisor);

401

402

/**

403

* Remove the advisor at the given index.

404

* @param index the index of advisor to remove

405

* @throws AopConfigException if the index is invalid

406

*/

407

void removeAdvisor(int index) throws AopConfigException;

408

409

/**

410

* Return the index (from 0) of the given advisor,

411

* or -1 if no such advisor applies to this proxy.

412

* <p>The return value of this method can be used to index into the advisors array.

413

* @param advisor the advisor to search for

414

* @return index from 0 of this advisor, or -1 if there's no such advisor

415

*/

416

int indexOf(Advisor advisor);

417

418

/**

419

* Replace the given advisor.

420

* <p><b>Note:</b> If the advisor is an {@link org.springframework.aop.IntroductionAdvisor}

421

* and the replacement is not or vice versa, the relevant interfaces will be added

422

* or removed from the proxied interfaces list.

423

* @param a the advisor to replace

424

* @param b the advisor to replace it with

425

* @return whether it was replaced. If the advisor wasn't found in the

426

* list of advisors, this method returns {@code false} and does nothing.

427

* @throws AopConfigException in case of invalid advice

428

*/

429

boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;

430

431

/**

432

* Add the given AOP Alliance advice to the tail of the advice (advisor) chain.

433

* <p>This will be wrapped in a DefaultPointcutAdvisor with a pointcut that always

434

* applies, and returned from the {@code getAdvisors()} method in this wrapped form.

435

* <p>Note that the given advice will apply to all invocations on the proxy,

436

* even to the {@code toString()} method! Use appropriate advice implementations

437

* or specify appropriate pointcuts to apply to a narrower set of methods.

438

* @param advice the advice to add to the tail of the chain

439

* @throws AopConfigException in case of invalid advice

440

* @see #addAdvice(int, Advice)

441

* @see org.springframework.aop.support.DefaultPointcutAdvisor

442

*/

443

void addAdvice(Advice advice) throws AopConfigException;

444

445

/**

446

* Add the given AOP Alliance Advice at the specified position in the advice chain.

447

* <p>This will be wrapped in a {@link org.springframework.aop.support.DefaultPointcutAdvisor}

448

* with a pointcut that always applies, and returned from the {@link #getAdvisors()}

449

* method in this wrapped form.

450

* <p>Note: The given advice will apply to all invocations on the proxy,

451

* even to the {@code toString()} method! Use appropriate advice implementations

452

* or specify appropriate pointcuts to apply to a narrower set of methods.

453

* @param pos index from 0 (head)

454

* @param advice advice to add at the specified position in the advice chain

455

* @throws AopConfigException in case of invalid advice

456

*/

457

void addAdvice(int pos, Advice advice) throws AopConfigException;

458

459

/**

460

* Remove the Advisor containing the given advice.

461

* @param advice the advice to remove

462

* @return {@code true} of the advice was found and removed;

463

* {@code false} if there was no such advice

464

*/

465

boolean removeAdvice(Advice advice);

466

467

/**

468

* Return the index (from 0) of the given AOP Alliance Advice,

469

* or -1 if no such advice is an advice for this proxy.

470

* <p>The return value of this method can be used to index into

471

* the advisors array.

472

* @param advice AOP Alliance advice to search for

473

* @return index from 0 of this advice, or -1 if there's no such advice

474

*/

475

int indexOf(Advice advice);

476

477

/**

478

* As {@code toString()} will normally be delegated to the target,

479

* this returns the equivalent for the AOP proxy.

480

* @return a string description of the proxy configuration

481

*/

482

String toProxyConfigString();

483

}

484

```

485

486

### Support Classes

487

488

Utility classes for AOP proxy creation and management.

489

490

```java { .api }

491

public final class AopContext {

492

/**

493

* Try to return the current AOP proxy. This method is usable only if the

494

* calling method has been invoked via AOP, and the AOP framework has been set

495

* to expose proxies. Otherwise, this method will throw an IllegalStateException.

496

* @return the current AOP proxy (never returns {@code null})

497

* @throws IllegalStateException if the proxy cannot be found, because the

498

* method was invoked outside an AOP invocation context, or because the

499

* AOP framework has not been configured to expose the proxy

500

*/

501

public static Object currentProxy() throws IllegalStateException;

502

}

503

504

public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanClassLoaderAware, AopInfrastructureBean {

505

/**

506

* This should run after all other processors, so that it can just add

507

* an advisor to existing proxies rather than double-proxy.

508

*/

509

private int order = Ordered.LOWEST_PRECEDENCE;

510

511

@Override

512

public void setBeanClassLoader(ClassLoader classLoader);

513

514

/**

515

* Return the currently configured {@link ClassLoader}, or {@code null}

516

* if none configured yet.

517

* <p>The default implementation simply returns {@code null}, as this

518

* base class does not hold a ClassLoader reference by default.

519

*/

520

protected ClassLoader getProxyClassLoader();

521

522

/**

523

* Check whether the given bean class is an infrastructure class that should

524

* never be proxied.

525

* <p>The default implementation considers Advices, Advisors and AopInfrastructureBeans

526

* as infrastructure classes.

527

* @param beanClass the class of the bean

528

* @return whether the bean represents an infrastructure class

529

* @see org.aopalliance.aop.Advice

530

* @see org.springframework.aop.Advisor

531

* @see org.springframework.aop.framework.AopInfrastructureBean

532

* @see #shouldSkip

533

*/

534

protected boolean isInfrastructureClass(Class<?> beanClass);

535

}

536

```

537

538

## Usage Examples

539

540

### Basic Proxy Creation

541

542

```java

543

// Create a simple proxy with method interceptor

544

Object target = new MyServiceImpl();

545

ProxyFactory factory = new ProxyFactory(target);

546

547

MethodInterceptor interceptor = invocation -> {

548

System.out.println("Before: " + invocation.getMethod().getName());

549

Object result = invocation.proceed();

550

System.out.println("After: " + invocation.getMethod().getName());

551

return result;

552

};

553

554

factory.addAdvice(interceptor);

555

MyService proxy = (MyService) factory.getProxy();

556

```

557

558

### Interface-Based Proxy

559

560

```java

561

// Proxy specific interfaces only

562

ProxyFactory factory = new ProxyFactory();

563

factory.setTarget(new MyServiceImpl());

564

factory.setInterfaces(MyService.class, AnotherInterface.class);

565

factory.addAdvice(new LoggingInterceptor());

566

567

MyService proxy = (MyService) factory.getProxy();

568

```

569

570

### Class-Based Proxy (CGLIB)

571

572

```java

573

// Force CGLIB proxying for target class

574

ProxyFactory factory = new ProxyFactory();

575

factory.setTarget(new ConcreteService());

576

factory.setProxyTargetClass(true); // Use CGLIB

577

factory.addAdvisor(new TransactionAdvisor());

578

579

ConcreteService proxy = (ConcreteService) factory.getProxy();

580

```

581

582

### Advanced Configuration

583

584

```java

585

ProxyFactory factory = new ProxyFactory();

586

factory.setTarget(target);

587

588

// Configure proxy behavior

589

factory.setOptimize(true);

590

factory.setFrozen(false);

591

factory.setExposeProxy(true);

592

factory.setPreFiltered(true);

593

594

// Add multiple advisors

595

factory.addAdvisor(new SecurityAdvisor());

596

factory.addAdvisor(new CachingAdvisor());

597

factory.addAdvisor(new LoggingAdvisor());

598

599

// Create proxy with custom class loader

600

Object proxy = factory.getProxy(Thread.currentThread().getContextClassLoader());

601

```

602

603

### Static Factory Methods

604

605

```java

606

// Convenience methods for common scenarios

607

MyService proxy1 = ProxyFactory.getProxy(MyService.class, loggingInterceptor);

608

609

TargetSource targetSource = new SingletonTargetSource(new MyServiceImpl());

610

MyService proxy2 = ProxyFactory.getProxy(MyService.class, targetSource);

611

```