diff --git a/spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyUtils.java b/spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyUtils.java index d75dac8d244..34479c0a453 100644 --- a/spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyUtils.java +++ b/spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2019 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. @@ -23,20 +23,25 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; /** * Utility class for creating a scoped proxy. - * Used by ScopedProxyBeanDefinitionDecorator and ClassPathBeanDefinitionScanner. + * + *
Used by ScopedProxyBeanDefinitionDecorator and ClassPathBeanDefinitionScanner. * * @author Mark Fisher * @author Juergen Hoeller * @author Rob Harrop + * @author Sam Brannen * @since 2.5 */ public abstract class ScopedProxyUtils { private static final String TARGET_NAME_PREFIX = "scopedTarget."; + private static final int TARGET_NAME_PREFIX_LENGTH = TARGET_NAME_PREFIX.length(); + /** * Generate a scoped proxy for the supplied target bean, registering the target @@ -45,6 +50,8 @@ public abstract class ScopedProxyUtils { * @param registry the bean definition registry * @param proxyTargetClass whether to create a target class proxy * @return the scoped proxy definition + * @see #getTargetBeanName(String) + * @see #getOriginalBeanName(String) */ public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition, BeanDefinitionRegistry registry, boolean proxyTargetClass) { @@ -93,11 +100,29 @@ public abstract class ScopedProxyUtils { * Generate the bean name that is used within the scoped proxy to reference the target bean. * @param originalBeanName the original name of bean * @return the generated bean to be used to reference the target bean + * @see #getOriginalBeanName(String) */ public static String getTargetBeanName(String originalBeanName) { return TARGET_NAME_PREFIX + originalBeanName; } + /** + * Get the original bean name for the provided {@linkplain #getTargetBeanName + * target bean name}. + * @param targetBeanName the target bean name for the scoped proxy + * @return the original bean name + * @throws IllegalArgumentException if the supplied bean name does not refer + * to the target of a scoped proxy + * @since 5.1.10 + * @see #getTargetBeanName(String) + * @see #isScopedTarget(String) + */ + public static String getOriginalBeanName(String targetBeanName) { + Assert.isTrue(isScopedTarget(targetBeanName), () -> "bean name '" + + targetBeanName + "' does not refer to the target of a scoped proxy"); + return targetBeanName.substring(TARGET_NAME_PREFIX_LENGTH); + } + /** * Specify if the {@code beanName} is the name of a bean that references the target * bean within a scoped proxy. diff --git a/spring-aop/src/test/java/org/springframework/aop/scope/ScopedProxyUtilsTests.java b/spring-aop/src/test/java/org/springframework/aop/scope/ScopedProxyUtilsTests.java new file mode 100644 index 00000000000..7c52fbcabe7 --- /dev/null +++ b/spring-aop/src/test/java/org/springframework/aop/scope/ScopedProxyUtilsTests.java @@ -0,0 +1,74 @@ +/* + * Copyright 2002-2019 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.aop.scope; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static org.junit.Assert.*; + +/** + * Unit tests for {@link ScopedProxyUtils}. + * + * @author Sam Brannen + * @since 5.1.10 + */ +public class ScopedProxyUtilsTests { + + @Rule + public final ExpectedException exception = ExpectedException.none(); + + + @Test + public void getTargetBeanNameAndIsScopedTarget() { + String originalBeanName = "myBean"; + String targetBeanName = ScopedProxyUtils.getTargetBeanName(originalBeanName); + + assertNotEquals(originalBeanName, targetBeanName); + assertTrue(targetBeanName.endsWith(originalBeanName)); + assertTrue(ScopedProxyUtils.isScopedTarget(targetBeanName)); + assertFalse(ScopedProxyUtils.isScopedTarget(originalBeanName)); + } + + @Test + public void getOriginalBeanNameAndIsScopedTarget() { + String originalBeanName = "myBean"; + String targetBeanName = ScopedProxyUtils.getTargetBeanName(originalBeanName); + String parsedOriginalBeanName = ScopedProxyUtils.getOriginalBeanName(targetBeanName); + + assertNotEquals(targetBeanName, parsedOriginalBeanName); + assertEquals(originalBeanName, parsedOriginalBeanName); + assertTrue(ScopedProxyUtils.isScopedTarget(targetBeanName)); + assertFalse(ScopedProxyUtils.isScopedTarget(parsedOriginalBeanName)); + } + + @Test + public void getOriginalBeanNameForNullTargetBean() { + exception.expect(IllegalArgumentException.class); + exception.expectMessage("bean name 'null' does not refer to the target of a scoped proxy"); + ScopedProxyUtils.getOriginalBeanName(null); + } + + @Test + public void getOriginalBeanNameForNonScopedTarget() { + exception.expect(IllegalArgumentException.class); + exception.expectMessage("bean name 'myBean' does not refer to the target of a scoped proxy"); + ScopedProxyUtils.getOriginalBeanName("myBean"); + } + +}