Do not proxy test instances based on "original instance" convention

Issue: SPR-17137
This commit is contained in:
Juergen Hoeller
2018-08-24 00:49:01 +02:00
parent f6ee2508ef
commit 9614817e88
10 changed files with 268 additions and 206 deletions

View File

@@ -385,14 +385,17 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
/**
* Subclasses should override this method to return {@code true} if the
* given bean should not be considered for auto-proxying by this post-processor.
* <p>Sometimes we need to be able to avoid this happening if it will lead to
* a circular reference. This implementation returns {@code false}.
* <p>Sometimes we need to be able to avoid this happening, e.g. if it will lead to
* a circular reference or if the existing target instance needs to be preserved.
* This implementation returns {@code false} unless the bean name indicates an
* "original instance" according to {@code AutowireCapableBeanFactory} conventions.
* @param beanClass the class of the bean
* @param beanName the name of the bean
* @return whether to skip the given bean
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#ORIGINAL_INSTANCE_SUFFIX
*/
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
return false;
return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 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.
@@ -64,4 +64,10 @@ public abstract class AbstractBeanFactoryAwareAdvisingPostProcessor extends Abst
return proxyFactory;
}
@Override
protected boolean isEligible(Object bean, String beanName) {
return (!AutoProxyUtils.isOriginalInstance(beanName, bean.getClass()) &&
super.isEligible(bean, beanName));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 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.
@@ -16,10 +16,12 @@
package org.springframework.aop.framework.autoproxy;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.Conventions;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
/**
* Utilities for auto-proxy aware components.
@@ -63,7 +65,9 @@ public abstract class AutoProxyUtils {
* @param beanName the name of the bean
* @return whether the given bean should be proxied with its target class
*/
public static boolean shouldProxyTargetClass(ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {
public static boolean shouldProxyTargetClass(
ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {
if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
return Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE));
@@ -81,7 +85,9 @@ public abstract class AutoProxyUtils {
* @see org.springframework.beans.factory.BeanFactory#getType(String)
*/
@Nullable
public static Class<?> determineTargetClass(ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {
public static Class<?> determineTargetClass(
ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {
if (beanName == null) {
return null;
}
@@ -102,12 +108,30 @@ public abstract class AutoProxyUtils {
* @param targetClass the corresponding target class
* @since 4.2.3
*/
static void exposeTargetClass(ConfigurableListableBeanFactory beanFactory, @Nullable String beanName,
Class<?> targetClass) {
static void exposeTargetClass(
ConfigurableListableBeanFactory beanFactory, @Nullable String beanName, Class<?> targetClass) {
if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
beanFactory.getMergedBeanDefinition(beanName).setAttribute(ORIGINAL_TARGET_CLASS_ATTRIBUTE, targetClass);
}
}
/**
* Determine whether the given bean name indicates an "original instance"
* according to {@link AutowireCapableBeanFactory#ORIGINAL_INSTANCE_SUFFIX},
* skipping any proxy attempts for it.
* @param beanName the name of the bean
* @param beanClass the corresponding bean class
* @since 5.1
* @see AutowireCapableBeanFactory#ORIGINAL_INSTANCE_SUFFIX
*/
static boolean isOriginalInstance(String beanName, Class<?> beanClass) {
if (!StringUtils.hasLength(beanName) || beanName.length() !=
beanClass.getName().length() + AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX.length()) {
return false;
}
return (beanName.startsWith(beanClass.getName()) &&
beanName.endsWith(AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX));
}
}