Skip to content

Commit 6411ed6

Browse files
sbrannenkenny5he
authored andcommitted
Only proxy supported beans in BeanNameAutoProxyCreator
Prior to this commit, if a BeanNameAutoProxyCreator was configured with a custom TargetSourceCreator, the TargetSourceCreator was applied to all beans in the ApplicationContext. Thus, the list of supported beanNames was effectively ignored when applying any TargetSourceCreator. Consequently, if a TargetSourceCreator returned a non-null TargetSource for a given bean, the BeanNameAutoProxyCreator proxied the bean even if the bean name had not been configured in the beanNames list. This commit addresses this issue by ensuring that a custom TargetSourceCreator is only applied to beans whose names match the configured beanNames list in a BeanNameAutoProxyCreator. Closes spring-projectsgh-24915
1 parent 2f5dc26 commit 6411ed6

File tree

3 files changed

+80
-13
lines changed

3 files changed

+80
-13
lines changed

spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/BeanNameAutoProxyCreator.java

+46-13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -37,6 +37,7 @@
3737
* "interceptorNames" property.
3838
*
3939
* @author Juergen Hoeller
40+
* @author Sam Brannen
4041
* @since 10.10.2003
4142
* @see #setBeanNames
4243
* @see #isMatch
@@ -46,6 +47,8 @@
4647
@SuppressWarnings("serial")
4748
public class BeanNameAutoProxyCreator extends AbstractAutoProxyCreator {
4849

50+
private static final String[] NO_ALIASES = new String[0];
51+
4952
@Nullable
5053
private List<String> beanNames;
5154

@@ -72,40 +75,70 @@ public void setBeanNames(String... beanNames) {
7275

7376

7477
/**
75-
* Identify as bean to proxy if the bean name is in the configured list of names.
78+
* Delegate to {@link AbstractAutoProxyCreator#getCustomTargetSource(Class, String)}
79+
* if the bean name matches one of the names in the configured list of supported
80+
* names, returning {@code null} otherwise.
81+
* @since 5.3
82+
* @see #setBeanNames(String...)
83+
*/
84+
@Override
85+
protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) {
86+
return (isSupportedBeanName(beanClass, beanName) ?
87+
super.getCustomTargetSource(beanClass, beanName) : null);
88+
}
89+
90+
/**
91+
* Identify as a bean to proxy if the bean name matches one of the names in
92+
* the configured list of supported names.
93+
* @see #setBeanNames(String...)
7694
*/
7795
@Override
7896
@Nullable
7997
protected Object[] getAdvicesAndAdvisorsForBean(
8098
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
8199

100+
return (isSupportedBeanName(beanClass, beanName) ?
101+
PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS : DO_NOT_PROXY);
102+
}
103+
104+
/**
105+
* Determine if the bean name for the given bean class matches one of the names
106+
* in the configured list of supported names.
107+
* @param beanClass the class of the bean to advise
108+
* @param beanName the name of the bean
109+
* @return {@code true} if the given bean name is supported
110+
* @see #setBeanNames(String...)
111+
*/
112+
private boolean isSupportedBeanName(Class<?> beanClass, String beanName) {
82113
if (this.beanNames != null) {
114+
boolean isFactoryBean = FactoryBean.class.isAssignableFrom(beanClass);
83115
for (String mappedName : this.beanNames) {
84-
if (FactoryBean.class.isAssignableFrom(beanClass)) {
116+
if (isFactoryBean) {
85117
if (!mappedName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
86118
continue;
87119
}
88120
mappedName = mappedName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
89121
}
90122
if (isMatch(beanName, mappedName)) {
91-
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
123+
return true;
92124
}
93-
BeanFactory beanFactory = getBeanFactory();
94-
if (beanFactory != null) {
95-
String[] aliases = beanFactory.getAliases(beanName);
96-
for (String alias : aliases) {
97-
if (isMatch(alias, mappedName)) {
98-
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
99-
}
125+
}
126+
127+
BeanFactory beanFactory = getBeanFactory();
128+
String[] aliases = (beanFactory != null ? beanFactory.getAliases(beanName) : NO_ALIASES);
129+
for (String alias : aliases) {
130+
for (String mappedName : this.beanNames) {
131+
if (isMatch(alias, mappedName)) {
132+
return true;
100133
}
101134
}
102135
}
103136
}
104-
return DO_NOT_PROXY;
137+
return false;
105138
}
106139

107140
/**
108-
* Return if the given bean name matches the mapped name.
141+
* Determine if the given bean name matches the mapped name.
109142
* <p>The default implementation checks for "xxx*", "*xxx" and "*xxx*" matches,
110143
* as well as direct equality. Can be overridden in subclasses.
111144
* @param beanName the bean name to check

spring-context/src/test/java/org/springframework/aop/framework/autoproxy/BeanNameAutoProxyCreatorTests.java

+10
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,16 @@ void withFrozenProxy() {
155155
assertThat(((Advised)testBean).isFrozen()).isTrue();
156156
}
157157

158+
@Test
159+
void customTargetSourceCreatorsApplyOnlyToConfiguredBeanNames() {
160+
ITestBean lazy1 = beanFactory.getBean("lazy1", ITestBean.class);
161+
ITestBean alias1 = beanFactory.getBean("lazy1alias", ITestBean.class);
162+
ITestBean lazy2 = beanFactory.getBean("lazy2", ITestBean.class);
163+
assertThat(AopUtils.isAopProxy(lazy1)).isTrue();
164+
assertThat(AopUtils.isAopProxy(alias1)).isTrue();
165+
assertThat(AopUtils.isAopProxy(lazy2)).isFalse();
166+
}
167+
158168

159169
private void jdkAssertions(ITestBean tb, int nopInterceptorCount) {
160170
NopInterceptor nop = (NopInterceptor) beanFactory.getBean("nopInterceptor");

spring-context/src/test/resources/org/springframework/aop/framework/autoproxy/BeanNameAutoProxyCreatorTests-context.xml

+24
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,28 @@
104104
<property name="name" value="noproxy" />
105105
</bean>
106106

107+
<bean id="lazy1" class="org.springframework.beans.testfixture.beans.TestBean" lazy-init="true">
108+
<property name="name" value="lazy1" />
109+
</bean>
110+
111+
<alias name="lazy1" alias="lazy1alias"/>
112+
113+
<bean id="lazy2" class="org.springframework.beans.testfixture.beans.TestBean" lazy-init="true">
114+
<property name="name" value="lazy2" />
115+
</bean>
116+
117+
<bean id="lazyBeanNameAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
118+
<property name="beanNames" value="lazy1" />
119+
<property name="customTargetSourceCreators">
120+
<bean class="org.springframework.aop.framework.autoproxy.target.LazyInitTargetSourceCreator" />
121+
</property>
122+
</bean>
123+
124+
<bean id="lazyAliasBeanNameAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
125+
<property name="beanNames" value="lazy1alias" />
126+
<property name="customTargetSourceCreators">
127+
<bean class="org.springframework.aop.framework.autoproxy.target.LazyInitTargetSourceCreator" />
128+
</property>
129+
</bean>
130+
107131
</beans>

0 commit comments

Comments
 (0)