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 gh-24915
This commit is contained in:
parent
a07dc80d72
commit
3c3e8e6a8b
|
@ -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.
|
||||
|
@ -37,6 +37,7 @@ import org.springframework.util.StringUtils;
|
|||
* "interceptorNames" property.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 10.10.2003
|
||||
* @see #setBeanNames
|
||||
* @see #isMatch
|
||||
|
@ -46,6 +47,8 @@ import org.springframework.util.StringUtils;
|
|||
@SuppressWarnings("serial")
|
||||
public class BeanNameAutoProxyCreator extends AbstractAutoProxyCreator {
|
||||
|
||||
private static final String[] NO_ALIASES = new String[0];
|
||||
|
||||
@Nullable
|
||||
private List<String> beanNames;
|
||||
|
||||
|
@ -72,40 +75,70 @@ public class BeanNameAutoProxyCreator extends AbstractAutoProxyCreator {
|
|||
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
|
@ -155,6 +155,16 @@ class BeanNameAutoProxyCreatorTests {
|
|||
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");
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue