0
# Auto-Proxy Creation
1
2
Automatic proxy creation through BeanPostProcessor implementations that analyze beans for advisor applicability and create proxies transparently during the Spring container initialization process. This system enables declarative AOP configuration where proxies are created automatically based on pointcut matching rather than explicit proxy factory configuration.
3
4
## Capabilities
5
6
### Base Auto-Proxy Creator
7
8
Abstract base class providing common functionality for automatic proxy creation during bean post-processing.
9
10
```java { .api }
11
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
12
implements BeanPostProcessor, BeanFactoryAware {
13
14
/**
15
* Set whether or not the proxy should be frozen, preventing advice
16
* from being added to it once it is created.
17
* <p>Overridden from the superclass to prevent the proxy configuration
18
* from being frozen before the proxy is created.
19
*/
20
@Override
21
public void setFrozen(boolean frozen);
22
23
/**
24
* Set the ordering which will apply to this class's implementation
25
* of Ordered, used when applying multiple BeanPostProcessors.
26
* <p>The default value is {@code Ordered.LOWEST_PRECEDENCE}, meaning non-ordered.
27
* @param order the ordering value
28
*/
29
public void setOrder(int order);
30
31
/**
32
* Return the order value of this object, with a higher value meaning greater
33
* precedence. Normally starting with 0, with {@code Integer.MAX_VALUE}
34
* indicating the greatest precedence (corresponding to the lowest priority).
35
*/
36
@Override
37
public int getOrder();
38
39
/**
40
* Set whether to apply advisors only to beans in this container,
41
* or to beans in the entire BeanFactory hierarchy.
42
* <p>Default is "false": apply advisors to beans in the entire BeanFactory
43
* hierarchy, i.e. including ancestor contexts (as far as they are visible
44
* from the ApplicationContext that this post-processor is defined in).
45
* <p>Switch this flag to "true" in order to apply advisors only to beans
46
* in the local ApplicationContext, ignoring beans in ancestor contexts.
47
* This can be useful if ancestor contexts are read-only, and if you want
48
* to avoid applying advisors to beans defined in read-only contexts.
49
* @param applyCommonInterceptorsFirst whether to apply advisors only locally
50
*/
51
public void setApplyCommonInterceptorsFirst(boolean applyCommonInterceptorsFirst);
52
53
/**
54
* Set custom {@code TargetSourceCreators} to apply to this configuration.
55
* If the list is empty, no custom TargetSource will be applied.
56
* <p>Note that TargetSourceCreators will only be applied if this post-processor
57
* actually creates a proxy for the specific bean. If there are competing
58
* post-processors or if the bean is not eligible for proxying for other reasons,
59
* no custom TargetSource will be applied.
60
* <p>TargetSourceCreators can only be invoked if this post-processor comes first
61
* in the list of BeanPostProcessors; otherwise, the TargetSource will not be
62
* in effect. Custom target sources are disabled by default.
63
* @param targetSourceCreators list of TargetSourceCreator
64
* implementations to apply in the given order
65
*/
66
public void setCustomTargetSourceCreators(TargetSourceCreator... targetSourceCreators);
67
68
/**
69
* Set the common interceptors. These must be bean names in the current factory.
70
* They can be of any advice or advisor type Spring supports.
71
* <p>If this property isn't set, there will be zero common interceptors.
72
* This is perfectly valid, if "specific" interceptors such as matching
73
* Advisors are all we want.
74
* @param interceptorNames the list of interceptor names
75
*/
76
public void setInterceptorNames(String... interceptorNames);
77
78
/**
79
* Set the BeanFactory to use. This will be used to retrieve the named
80
* interceptors set in this class.
81
*/
82
@Override
83
public void setBeanFactory(BeanFactory beanFactory);
84
85
/**
86
* Return the owning BeanFactory.
87
* May be {@code null}, as this post-processor doesn't need to belong to a bean factory.
88
*/
89
protected BeanFactory getBeanFactory();
90
91
/**
92
* Create a proxy with the configured interceptors if the bean is
93
* identified as one to proxy by the subclass.
94
* @see #getAdvicesAndAdvisorsForBean
95
*/
96
@Override
97
public Object postProcessBeforeInitialization(Object bean, String beanName);
98
99
/**
100
* Create a proxy with the configured interceptors if the bean is
101
* identified as one to proxy by the subclass.
102
* @see #getAdvicesAndAdvisorsForBean
103
*/
104
@Override
105
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
106
107
/**
108
* Return an array of additional interceptors (or advisors) for the
109
* given bean. Is called if the bean is eligible for proxying.
110
* <p>The returned advisors will be applied to the bean in addition to
111
* any advisors corresponding to common interceptors for the proxy.
112
* Advisors are invoked in the order specified.
113
* <p>The default implementation returns the given advisors as-is.
114
* @param advisors the advisors obtained so far for the particular bean
115
* @param beanName the name of the bean
116
* @param targetClass the class of the bean to be advised
117
* @return the additional advisors for the particular bean;
118
* or the given advisors as-is.
119
* The return value will be added to the advisors list.
120
* Null means no additional advisor.
121
* @throws BeansException in case of errors
122
*/
123
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource customTargetSource) throws BeansException;
124
125
/**
126
* Subclasses should override this to return {@code true} if the
127
* given bean should not be considered for auto-proxying.
128
* <p>Sometimes we need to be able to avoid this happening, e.g. if it will lead to
129
* a circular reference or if the existing target instance needs to be preserved.
130
* This implementation returns {@code false} unless the bean name indicates an
131
* "original instance" according to {@code AutoProxyUtils.isOriginalInstance}.
132
* @param beanClass the class of the bean
133
* @param beanName the name of the bean
134
* @return whether to skip the given bean
135
*/
136
protected boolean shouldSkip(Class<?> beanClass, String beanName);
137
138
/**
139
* Create a target source for bean instances. Uses any TargetSourceCreators if set.
140
* Returns {@code null} if no custom TargetSource should be used.
141
* <p>This implementation uses the "customTargetSourceCreators" property.
142
* Subclasses can override this method to use a different mechanism.
143
* @param beanClass the class of the bean to create a TargetSource for
144
* @param beanName the name of the bean
145
* @return a TargetSource for this bean
146
* @see #setCustomTargetSourceCreators
147
*/
148
protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName);
149
150
/**
151
* Create an AOP proxy for the given bean.
152
* @param beanClass the class of the bean
153
* @param beanName the name of the bean
154
* @param specificInterceptors the set of interceptors that is
155
* specific to this bean (may be empty, but not null)
156
* @param targetSource the TargetSource for the proxy,
157
* already pre-configured to access the bean
158
* @return the AOP proxy for the bean
159
* @see #buildAdvisors
160
*/
161
protected Object createProxy(Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource);
162
163
/**
164
* Determine the advisors for the given bean, including the specific interceptors
165
* as well as the common interceptor, all adapted to the Advisor interface.
166
* @param beanName the name of the bean
167
* @param specificInterceptors the set of interceptors that is
168
* specific to this bean (may be empty, but not null)
169
* @return the list of Advisors for the given bean
170
*/
171
protected Advisor[] buildAdvisors(String beanName, Object[] specificInterceptors);
172
}
173
```
174
175
### Advisor-Based Auto-Proxy Creators
176
177
Auto-proxy creators that work with Advisor beans in the application context.
178
179
```java { .api }
180
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
181
/**
182
* Set whether to use the bean name of the advisor bean as the advisor's name,
183
* instead of the default advisor name (which is the simple class name).
184
* <p>Default is "false".
185
* @param useAdvisorBeanNameAsAdvisorName whether to use the bean name as advisor name
186
*/
187
public void setUseAdvisorBeanNameAsAdvisorName(boolean useAdvisorBeanNameAsAdvisorName);
188
189
/**
190
* Return whether to use the bean name of the advisor bean as advisor name.
191
*/
192
public boolean isUseAdvisorBeanNameAsAdvisorName();
193
194
@Override
195
public void setBeanFactory(BeanFactory beanFactory);
196
197
/**
198
* Find all candidate Advisors to use in auto-proxying.
199
* @return the List of candidate Advisors
200
*/
201
protected List<Advisor> findCandidateAdvisors();
202
203
/**
204
* Search the given candidate Advisors to find all Advisors that
205
* can apply to the specified bean.
206
* @param candidateAdvisors the candidate Advisors
207
* @param beanClass the target's bean class
208
* @param beanName the target's bean name
209
* @return the List of applicable Advisors
210
* @see ProxyCreationContext#getCurrentProxiedBeanName()
211
*/
212
protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName);
213
214
/**
215
* Return whether the Advisor bean with the given name is eligible
216
* for proxying in the first place.
217
* @param beanName the name of the Advisor bean
218
* @return whether the bean is eligible
219
*/
220
protected boolean isEligibleAdvisorBean(String beanName);
221
222
/**
223
* Sort advisors based on ordering. Subclasses may choose to override this
224
* method to customize the sorting algorithm.
225
* @param advisors the source List of Advisors
226
* @return the sorted List of Advisors
227
* @see org.springframework.core.Ordered
228
* @see org.springframework.core.annotation.Order
229
* @see org.springframework.core.annotation.AnnotationAwareOrderComparator
230
*/
231
protected List<Advisor> sortAdvisors(List<Advisor> advisors);
232
233
/**
234
* Extension point that allows for providing a custom instance of the
235
* AutoProxyUtils that is used by auto-proxy creators.
236
* <p>The default implementation returns {@code DefaultAutoProxyUtils}.
237
* @return the AutoProxyUtils instance to use
238
* @since 4.2.3
239
*/
240
protected AutoProxyUtils getAutoProxyUtils();
241
}
242
243
public class DefaultAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
244
/**
245
* A marker prefix indicating that the bean name following the prefix is an advisor
246
* that should be included in the proxying process.
247
*/
248
public static final String ADVISOR_BEAN_NAME_PREFIX = "org.springframework.aop.Advisor.";
249
250
/**
251
* Set the prefix that advisor bean names must have.
252
* <p>The default value is {@link #ADVISOR_BEAN_NAME_PREFIX}.
253
* @param advisorBeanNamePrefix the required prefix for advisor bean names
254
*/
255
public void setAdvisorBeanNamePrefix(String advisorBeanNamePrefix);
256
257
/**
258
* Return the prefix that advisor bean names must have.
259
*/
260
public String getAdvisorBeanNamePrefix();
261
}
262
263
public class InfrastructureAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
264
@Override
265
protected boolean isEligibleAdvisorBean(String beanName);
266
}
267
```
268
269
### Bean Name-Based Auto-Proxy Creator
270
271
Auto-proxy creator that selects beans for proxying based on their bean names.
272
273
```java { .api }
274
public class BeanNameAutoProxyCreator extends AbstractAutoProxyCreator {
275
/**
276
* Set the names of the beans that should automatically get wrapped with proxies.
277
* A name can specify a prefix to match by ending with "*", e.g. "myBean,tx*"
278
* will match the bean named "myBean" and all beans whose name start with "tx".
279
* <p><b>NOTE:</b> In case of a FactoryBean, only the objects created by the
280
* FactoryBean will get proxied. This default behavior applies as of Spring 2.0.
281
* If you intend to proxy a FactoryBean itself, specify the bean name of the
282
* FactoryBean including the factory-bean prefix "&": e.g. "&myFactoryBean".
283
* @param beanNames the list of bean names
284
*/
285
public void setBeanNames(String... beanNames);
286
287
/**
288
* Set the common interceptors. These must be bean names in the current factory.
289
* They can be of any advice or advisor type Spring supports.
290
* <p>If this property isn't set, there will be zero common interceptors.
291
* This is perfectly valid, if "specific" interceptors such as matching
292
* Advisors are all we want.
293
* @param interceptorNames the list of interceptor names
294
*/
295
public void setInterceptorNames(String... interceptorNames);
296
297
/**
298
* Identify as a bean to proxy if the bean name is in the configured list of names.
299
*/
300
@Override
301
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource customTargetSource);
302
303
/**
304
* Check whether the given bean name is in the configured list of bean names.
305
* @param beanName the bean name to check
306
* @return whether the given bean name is in the configured list of bean names
307
*/
308
protected boolean isMatch(String beanName);
309
}
310
```
311
312
### AspectJ-Aware Auto-Proxy Creator
313
314
Auto-proxy creator that integrates with AspectJ for advanced pointcut expressions and aspect processing.
315
316
```java { .api }
317
public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
318
@Override
319
protected List<Advisor> sortAdvisors(List<Advisor> advisors);
320
321
/**
322
* Add an AspectJPrecedenceComparator decorator to the List returned by
323
* the superclass, so that AspectJ advisors are sorted according to AspectJ rules.
324
* @param advisors the source List of Advisors
325
* @return the sorted List of Advisors
326
* @see org.springframework.aop.aspectj.annotation.AspectJPrecedenceComparator
327
*/
328
@Override
329
protected List<Advisor> sortAdvisors(List<Advisor> advisors);
330
}
331
332
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
333
/**
334
* Set the list of aspect types for which to create Spring AOP Advisors.
335
* <p>Note: This is supported but not usually necessary. By default, Spring
336
* will automatically detect any @AspectJ classes in the application context.
337
* @param aspectClassNames the list of aspect class names
338
*/
339
public void setIncludePatterns(List<String> includePatterns);
340
341
/**
342
* Set the BeanNameAware bean names for this post-processor.
343
* <p>Note: This is supported but not usually necessary. By default, Spring
344
* will automatically detect any @AspectJ classes in the application context.
345
* @param aspectNames the list of aspect names
346
*/
347
public void setAspectNames(List<String> aspectNames);
348
349
/**
350
* Find all candidate Advisors to use in auto-proxying.
351
* @return the List of candidate Advisors
352
*/
353
@Override
354
protected List<Advisor> findCandidateAdvisors();
355
356
/**
357
* Build AspectJ advisors for all AspectJ aspects in the bean factory.
358
* @see #buildAspectJAdvisors()
359
*/
360
protected List<Advisor> buildAspectJAdvisors();
361
362
@Override
363
protected boolean shouldSkip(Class<?> beanClass, String beanName);
364
365
/**
366
* Check whether the given aspect bean is eligible for auto-proxying.
367
* <p>If no <aop:include> elements were used then "includePatterns" will be
368
* {@code null} and all beans are included. If "includePatterns" is non-null,
369
* then one of the patterns must match.
370
* @param beanName the name of the aspect bean
371
* @return whether the bean is eligible
372
*/
373
protected boolean isEligibleAspectBean(String beanName);
374
}
375
```
376
377
### Support Classes
378
379
Helper classes for auto-proxy creation functionality.
380
381
```java { .api }
382
public class BeanFactoryAdvisorRetrievalHelper {
383
/**
384
* Create a new BeanFactoryAdvisorRetrievalHelper for the given BeanFactory.
385
* @param beanFactory the ListableBeanFactory to scan
386
*/
387
public BeanFactoryAdvisorRetrievalHelper(ListableBeanFactory beanFactory);
388
389
/**
390
* Find all eligible Advisor beans in the current bean factory,
391
* ignoring FactoryBeans and excluding beans that are currently in creation.
392
* @return the list of {@link org.springframework.aop.Advisor} beans
393
* @see #isEligibleBean
394
*/
395
public List<Advisor> findAdvisorBeans();
396
397
/**
398
* Determine whether the aspect bean with the given name is eligible.
399
* <p>The default implementation always returns {@code true}.
400
* @param beanName the name of the aspect bean
401
* @param beanDefinition the corresponding bean definition
402
* @return whether the bean is eligible
403
*/
404
protected boolean isEligibleBean(String beanName, BeanDefinition beanDefinition);
405
}
406
407
public interface TargetSourceCreator {
408
/**
409
* Create a special TargetSource for the given bean, if any.
410
* @param beanClass the class of the bean to create a TargetSource for
411
* @param beanName the name of the bean
412
* @return a special TargetSource or {@code null} if this TargetSourceCreator isn't
413
* interested in the particular bean
414
*/
415
TargetSource getTargetSource(Class<?> beanClass, String beanName);
416
}
417
```
418
419
## Usage Examples
420
421
### Configuring Default Advisor Auto-Proxy Creator
422
423
```java
424
@Configuration
425
@EnableAspectJAutoProxy
426
public class AopConfig {
427
428
// Define advisor beans - they will be automatically applied
429
@Bean
430
public Advisor transactionAdvisor() {
431
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
432
pointcut.setExpression("@annotation(org.springframework.transaction.annotation.Transactional)");
433
return new DefaultPointcutAdvisor(pointcut, new TransactionInterceptor());
434
}
435
436
@Bean
437
public Advisor securityAdvisor() {
438
NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
439
pointcut.setMappedNames("secure*", "admin*");
440
return new DefaultPointcutAdvisor(pointcut, new SecurityInterceptor());
441
}
442
}
443
```
444
445
### Custom Auto-Proxy Creator
446
447
```java
448
@Component
449
public class CustomAutoProxyCreator extends AbstractAutoProxyCreator {
450
451
@Override
452
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource customTargetSource) {
453
// Custom logic to determine which beans should be proxied
454
if (beanClass.isAnnotationPresent(MyCustomAnnotation.class)) {
455
return new Object[] {
456
new LoggingInterceptor(),
457
new PerformanceInterceptor()
458
};
459
}
460
return DO_NOT_PROXY;
461
}
462
463
@Override
464
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
465
// Skip internal Spring beans and configuration classes
466
return super.shouldSkip(beanClass, beanName) ||
467
beanClass.isAnnotationPresent(Configuration.class);
468
}
469
}
470
```
471
472
### Bean Name Auto-Proxy Creator Configuration
473
474
```java
475
@Configuration
476
public class BeanNameAutoProxyConfig {
477
478
@Bean
479
public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
480
BeanNameAutoProxyCreator creator = new BeanNameAutoProxyCreator();
481
creator.setBeanNames("*Service", "*Repository", "userManager");
482
creator.setInterceptorNames("loggingInterceptor", "transactionInterceptor");
483
return creator;
484
}
485
486
@Bean
487
public MethodInterceptor loggingInterceptor() {
488
return invocation -> {
489
System.out.println("Calling: " + invocation.getMethod().getName());
490
Object result = invocation.proceed();
491
System.out.println("Finished: " + invocation.getMethod().getName());
492
return result;
493
};
494
}
495
496
@Bean
497
public MethodInterceptor transactionInterceptor() {
498
return invocation -> {
499
System.out.println("Starting transaction");
500
try {
501
Object result = invocation.proceed();
502
System.out.println("Committing transaction");
503
return result;
504
} catch (Exception e) {
505
System.out.println("Rolling back transaction");
506
throw e;
507
}
508
};
509
}
510
}
511
```
512
513
### Advanced AspectJ Auto-Proxy Configuration
514
515
```java
516
@Configuration
517
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
518
public class AdvancedAopConfig {
519
520
@Bean
521
public AnnotationAwareAspectJAutoProxyCreator autoProxyCreator() {
522
AnnotationAwareAspectJAutoProxyCreator creator = new AnnotationAwareAspectJAutoProxyCreator();
523
creator.setProxyTargetClass(true);
524
creator.setExposeProxy(true);
525
creator.setOrder(Ordered.HIGHEST_PRECEDENCE);
526
527
// Only process beans matching these patterns
528
creator.setIncludePatterns(Arrays.asList(".*Service.*", ".*Controller.*"));
529
530
return creator;
531
}
532
533
@Aspect
534
@Component
535
public class PerformanceAspect {
536
537
@Around("@annotation(org.springframework.cache.annotation.Cacheable)")
538
public Object measureCacheablePerformance(ProceedingJoinPoint joinPoint) throws Throwable {
539
long start = System.currentTimeMillis();
540
Object result = joinPoint.proceed();
541
long executionTime = System.currentTimeMillis() - start;
542
System.out.println("Cacheable method " + joinPoint.getSignature() +
543
" executed in " + executionTime + "ms");
544
return result;
545
}
546
}
547
}
548
```
549
550
### Infrastructure-Only Auto-Proxy Creator
551
552
```java
553
@Configuration
554
public class InfrastructureAopConfig {
555
556
@Bean
557
public InfrastructureAdvisorAutoProxyCreator infrastructureAutoProxyCreator() {
558
return new InfrastructureAdvisorAutoProxyCreator();
559
}
560
561
// Only infrastructure advisors will be applied
562
@Bean
563
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
564
public Advisor infrastructureAdvisor() {
565
return new DefaultPointcutAdvisor(
566
new AnnotationMatchingPointcut(Repository.class),
567
new DataAccessExceptionInterceptor()
568
);
569
}
570
}
571
```