Skip to content

Commit

Permalink
Only proxy supported beans in BeanNameAutoProxyCreator
Browse files Browse the repository at this point in the history
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 gh-24915
  • Loading branch information
sbrannen committed May 12, 2020
1 parent a07dc80 commit 3c3e8e6
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -37,6 +37,7 @@
* "interceptorNames" property.
*
* @author Juergen Hoeller
* @author Sam Brannen
* @since 10.10.2003
* @see #setBeanNames
* @see #isMatch
Expand All @@ -46,6 +47,8 @@
@SuppressWarnings("serial")
public class BeanNameAutoProxyCreator extends AbstractAutoProxyCreator {

private static final String[] NO_ALIASES = new String[0];

@Nullable
private List<String> beanNames;

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


/**
* Identify as bean to proxy if the bean name is in the configured list of names.
* Delegate to {@link AbstractAutoProxyCreator#getCustomTargetSource(Class, String)}
* if the bean name matches one of the names in the configured list of supported
* names, returning {@code null} otherwise.
* @since 5.3
* @see #setBeanNames(String...)
*/
@Override
protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) {
return (isSupportedBeanName(beanClass, beanName) ?
super.getCustomTargetSource(beanClass, beanName) : null);
}

/**
* Identify as a bean to proxy if the bean name matches one of the names in
* the configured list of supported names.
* @see #setBeanNames(String...)
*/
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

return (isSupportedBeanName(beanClass, beanName) ?
PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS : DO_NOT_PROXY);
}

/**
* Determine if the bean name for the given bean class matches one of the names
* in the configured list of supported names.
* @param beanClass the class of the bean to advise
* @param beanName the name of the bean
* @return {@code true} if the given bean name is supported
* @see #setBeanNames(String...)
*/
private boolean isSupportedBeanName(Class<?> beanClass, String beanName) {
if (this.beanNames != null) {
boolean isFactoryBean = FactoryBean.class.isAssignableFrom(beanClass);
for (String mappedName : this.beanNames) {
if (FactoryBean.class.isAssignableFrom(beanClass)) {
if (isFactoryBean) {
if (!mappedName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
continue;
}
mappedName = mappedName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
if (isMatch(beanName, mappedName)) {
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
return true;
}
BeanFactory beanFactory = getBeanFactory();
if (beanFactory != null) {
String[] aliases = beanFactory.getAliases(beanName);
for (String alias : aliases) {
if (isMatch(alias, mappedName)) {
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
}

BeanFactory beanFactory = getBeanFactory();
String[] aliases = (beanFactory != null ? beanFactory.getAliases(beanName) : NO_ALIASES);
for (String alias : aliases) {
for (String mappedName : this.beanNames) {
if (isMatch(alias, mappedName)) {
return true;
}
}
}
}
return DO_NOT_PROXY;
return false;
}

/**
* Return if the given bean name matches the mapped name.
* Determine if the given bean name matches the mapped name.
* <p>The default implementation checks for "xxx*", "*xxx" and "*xxx*" matches,
* as well as direct equality. Can be overridden in subclasses.
* @param beanName the bean name to check
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,16 @@ void withFrozenProxy() {
assertThat(((Advised)testBean).isFrozen()).isTrue();
}

@Test
void customTargetSourceCreatorsApplyOnlyToConfiguredBeanNames() {
ITestBean lazy1 = beanFactory.getBean("lazy1", ITestBean.class);
ITestBean alias1 = beanFactory.getBean("lazy1alias", ITestBean.class);
ITestBean lazy2 = beanFactory.getBean("lazy2", ITestBean.class);
assertThat(AopUtils.isAopProxy(lazy1)).isTrue();
assertThat(AopUtils.isAopProxy(alias1)).isTrue();
assertThat(AopUtils.isAopProxy(lazy2)).isFalse();
}


private void jdkAssertions(ITestBean tb, int nopInterceptorCount) {
NopInterceptor nop = (NopInterceptor) beanFactory.getBean("nopInterceptor");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,28 @@
<property name="name" value="noproxy" />
</bean>

<bean id="lazy1" class="org.springframework.beans.testfixture.beans.TestBean" lazy-init="true">
<property name="name" value="lazy1" />
</bean>

<alias name="lazy1" alias="lazy1alias"/>

<bean id="lazy2" class="org.springframework.beans.testfixture.beans.TestBean" lazy-init="true">
<property name="name" value="lazy2" />
</bean>

<bean id="lazyBeanNameAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames" value="lazy1" />
<property name="customTargetSourceCreators">
<bean class="org.springframework.aop.framework.autoproxy.target.LazyInitTargetSourceCreator" />
</property>
</bean>

<bean id="lazyAliasBeanNameAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames" value="lazy1alias" />
<property name="customTargetSourceCreators">
<bean class="org.springframework.aop.framework.autoproxy.target.LazyInitTargetSourceCreator" />
</property>
</bean>

</beans>

0 comments on commit 3c3e8e6

Please sign in to comment.