From bb6349f8ccc34350bd2daeeb66dcfd659ecbd8c3 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Sat, 1 Nov 2014 12:58:08 +0100 Subject: [PATCH] SimpleMetadataReaderFactory is capable of resolving inner class names with dot syntax now (analogous to ClassUtils.forName) Issue: SPR-12390 (cherry picked from commit 2d874d7) --- .../ConfigurationClassPostProcessorTests.java | 14 ++++++++++++- .../SimpleMetadataReaderFactory.java | 20 +++++++++++++++++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java index 815c487294d..87141668553 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 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. @@ -26,6 +26,7 @@ import org.springframework.beans.factory.support.RootBeanDefinition; /** * @author Chris Beams + * @author Juergen Hoeller */ public class ConfigurationClassPostProcessorTests { @@ -49,6 +50,17 @@ public class ConfigurationClassPostProcessorTests { assertSame(foo, bar.foo); } + @Test + public void configurationIntrospectionOfInnerClassesWorksWithDotNameSyntax() { + DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); + beanFactory.registerBeanDefinition("config", new RootBeanDefinition(getClass().getName() + ".SingletonBeanConfig")); + ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); + pp.postProcessBeanFactory(beanFactory); + Foo foo = beanFactory.getBean("foo", Foo.class); + Bar bar = beanFactory.getBean("bar", Bar.class); + assertSame(foo, bar.foo); + } + /** * Tests the fix for SPR-5655, a special workaround that prefers reflection * over ASM if a bean class is already loaded. diff --git a/spring-core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReaderFactory.java b/spring-core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReaderFactory.java index 2d8b40b5244..9e1c736fc91 100644 --- a/spring-core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReaderFactory.java +++ b/spring-core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReaderFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2014 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. @@ -73,7 +73,23 @@ public class SimpleMetadataReaderFactory implements MetadataReaderFactory { public MetadataReader getMetadataReader(String className) throws IOException { String resourcePath = ResourceLoader.CLASSPATH_URL_PREFIX + ClassUtils.convertClassNameToResourcePath(className) + ClassUtils.CLASS_FILE_SUFFIX; - return getMetadataReader(this.resourceLoader.getResource(resourcePath)); + Resource resource = this.resourceLoader.getResource(resourcePath); + if (!resource.exists()) { + // Maybe an inner class name using the dot name syntax? Need to use the dollar syntax here... + // ClassUtils.forName has an equivalent check for resolution into Class references later on. + int lastDotIndex = className.lastIndexOf('.'); + if (lastDotIndex != -1) { + String innerClassName = + className.substring(0, lastDotIndex) + '$' + className.substring(lastDotIndex + 1); + String innerClassResourcePath = ResourceLoader.CLASSPATH_URL_PREFIX + + ClassUtils.convertClassNameToResourcePath(innerClassName) + ClassUtils.CLASS_FILE_SUFFIX; + Resource innerClassResource = this.resourceLoader.getResource(innerClassResourcePath); + if (innerClassResource.exists()) { + resource = innerClassResource; + } + } + } + return getMetadataReader(resource); } public MetadataReader getMetadataReader(Resource resource) throws IOException {