diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactoryUtils.java b/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactoryUtils.java index 2c37b5dfa65..8ed7394a0e2 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactoryUtils.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/BeanFactoryUtils.java @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.springframework.beans.BeansException; import org.springframework.core.ResolvableType; @@ -51,6 +52,13 @@ public abstract class BeanFactoryUtils { */ public static final String GENERATED_BEAN_NAME_SEPARATOR = "#"; + /** + * Cache from name with factory bean prefix to stripped name without dereference. + * @since 5.1 + * @see BeanFactory#FACTORY_BEAN_PREFIX + */ + private static final Map transformedBeanNameCache = new ConcurrentHashMap<>(); + /** * Return whether the given name is a factory dereference @@ -72,11 +80,16 @@ public abstract class BeanFactoryUtils { */ public static String transformedBeanName(String name) { Assert.notNull(name, "'name' must not be null"); - String beanName = name; - while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) { - beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length()); + if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) { + return name; } - return beanName; + return transformedBeanNameCache.computeIfAbsent(name, beanName -> { + do { + beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length()); + } + while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)); + return beanName; + }); } /** diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/xml/XmlListableBeanFactoryTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/xml/XmlListableBeanFactoryTests.java index 25848af501f..15b8ad914a6 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/xml/XmlListableBeanFactoryTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/xml/XmlListableBeanFactoryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 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. @@ -42,30 +42,33 @@ import static org.junit.Assert.*; * @author Juergen Hoeller * @since 09.11.2003 */ -@SuppressWarnings({ "rawtypes", "unchecked" }) +@SuppressWarnings({"rawtypes", "unchecked"}) public class XmlListableBeanFactoryTests extends AbstractListableBeanFactoryTests { private DefaultListableBeanFactory parent; private DefaultListableBeanFactory factory; + @Before - public void setUp() { + public void setup() { parent = new DefaultListableBeanFactory(); - Map m = new HashMap(); - m.put("name", "Albert"); + + Map map = new HashMap(); + map.put("name", "Albert"); RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class); - bd1.setPropertyValues(new MutablePropertyValues(m)); + bd1.setPropertyValues(new MutablePropertyValues(map)); parent.registerBeanDefinition("father", bd1); - m = new HashMap(); - m.put("name", "Roderick"); + + map = new HashMap(); + map.put("name", "Roderick"); RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class); - bd2.setPropertyValues(new MutablePropertyValues(m)); + bd2.setPropertyValues(new MutablePropertyValues(map)); parent.registerBeanDefinition("rod", bd2); this.factory = new DefaultListableBeanFactory(parent); - new XmlBeanDefinitionReader(this.factory).loadBeanDefinitions( - new ClassPathResource("test.xml", getClass())); + new XmlBeanDefinitionReader(this.factory).loadBeanDefinitions(new ClassPathResource("test.xml", getClass())); + this.factory.addBeanPostProcessor(new BeanPostProcessor() { @Override public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException { @@ -82,9 +85,10 @@ public class XmlListableBeanFactoryTests extends AbstractListableBeanFactoryTest return bean; } }); + this.factory.addBeanPostProcessor(new LifecycleBean.PostProcessor()); this.factory.addBeanPostProcessor(new ProtectedLifecycleBean.PostProcessor()); - //this.factory.preInstantiateSingletons(); + // this.factory.preInstantiateSingletons(); } @Override @@ -92,6 +96,7 @@ public class XmlListableBeanFactoryTests extends AbstractListableBeanFactoryTest return factory; } + @Test @Override public void count() { @@ -104,19 +109,19 @@ public class XmlListableBeanFactoryTests extends AbstractListableBeanFactoryTest } @Test - public void lifecycleMethods() throws Exception { + public void lifecycleMethods() { LifecycleBean bean = (LifecycleBean) getBeanFactory().getBean("lifecycle"); bean.businessMethod(); } @Test - public void protectedLifecycleMethods() throws Exception { + public void protectedLifecycleMethods() { ProtectedLifecycleBean bean = (ProtectedLifecycleBean) getBeanFactory().getBean("protectedLifecycle"); bean.businessMethod(); } @Test - public void descriptionButNoProperties() throws Exception { + public void descriptionButNoProperties() { TestBean validEmpty = (TestBean) getBeanFactory().getBean("validEmptyWithDescription"); assertEquals(0, validEmpty.getAge()); } @@ -125,7 +130,7 @@ public class XmlListableBeanFactoryTests extends AbstractListableBeanFactoryTest * Test that properties with name as well as id creating an alias up front. */ @Test - public void autoAliasing() throws Exception { + public void autoAliasing() { List beanNames = Arrays.asList(getListableBeanFactory().getBeanDefinitionNames()); TestBean tb1 = (TestBean) getBeanFactory().getBean("aliased"); @@ -224,7 +229,7 @@ public class XmlListableBeanFactoryTests extends AbstractListableBeanFactoryTest } @Test - public void beanPostProcessor() throws Exception { + public void beanPostProcessor() { TestBean kerry = (TestBean) getBeanFactory().getBean("kerry"); TestBean kathy = (TestBean) getBeanFactory().getBean("kathy"); DummyFactory factory = (DummyFactory) getBeanFactory().getBean("&singletonFactory");