From d3a406876834b91a4cf3b1e840855caeb0446d28 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 23 Apr 2013 13:49:25 +0200 Subject: [PATCH] Minimized ASM usage In particular, avoid accidental usage of ASM for core JDK types - which will fail in case of a new bytecode version in the JDK, even if the application itself has been compiled with an earlier bytecode target. Issue: SPR-10292 --- .../AnnotatedGenericBeanDefinition.java | 14 +- .../annotation/ConfigurationClass.java | 7 +- ...onfigurationClassBeanDefinitionReader.java | 4 +- .../annotation/ConfigurationClassParser.java | 229 +++++++++++------- ...tedConfigurationClassEnhancementTests.java | 4 +- ...lVariableTableParameterNameDiscoverer.java | 11 +- .../core/type/StandardAnnotationMetadata.java | 4 +- .../AnnotationMetadataReadingVisitor.java | 19 +- .../classreading/SimpleMetadataReader.java | 2 +- .../EnableTransactionManagementTests.java | 14 +- .../EnableCachingIntegrationTests.java | 15 +- ...TransactionManagementIntegrationTests.java | 5 +- 12 files changed, 198 insertions(+), 130 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AnnotatedGenericBeanDefinition.java b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AnnotatedGenericBeanDefinition.java index f0fd4c5cac..53c1011b8c 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AnnotatedGenericBeanDefinition.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AnnotatedGenericBeanDefinition.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -58,15 +58,19 @@ public class AnnotatedGenericBeanDefinition extends GenericBeanDefinition implem * allowing for ASM-based processing and avoidance of early loading of the bean class. * Note that this constructor is functionally equivalent to * {@link org.springframework.context.annotation.ScannedGenericBeanDefinition - * ScannedGenericBeanDefinition}, however the semantics of the latter indicate that - * a bean was discovered specifically via component-scanning as opposed to other - * means. + * ScannedGenericBeanDefinition}, however the semantics of the latter indicate that a + * bean was discovered specifically via component-scanning as opposed to other means. * @param metadata the annotation metadata for the bean class in question * @since 3.1.1 */ public AnnotatedGenericBeanDefinition(AnnotationMetadata metadata) { Assert.notNull(metadata, "AnnotationMetadata must not be null"); - setBeanClassName(metadata.getClassName()); + if (metadata instanceof StandardAnnotationMetadata) { + setBeanClass(((StandardAnnotationMetadata) metadata).getIntrospectedClass()); + } + else { + setBeanClassName(metadata.getClassName()); + } this.metadata = metadata; } diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java index a25fdcf4ce..0a5a646092 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -81,7 +81,7 @@ final class ConfigurationClass { * using the {@link Import} annotation or automatically processed as a nested * configuration class (if imported is {@code true}). * @param metadataReader reader used to parse the underlying {@link Class} - * @param beanName name of the {@code @Configuration} class bean + * @param imported whether the given configuration class is being imported * @since 3.1.1 */ public ConfigurationClass(MetadataReader metadataReader, boolean imported) { @@ -110,7 +110,7 @@ final class ConfigurationClass { * using the {@link Import} annotation or automatically processed as a nested * configuration class (if imported is {@code true}). * @param clazz the underlying {@link Class} to represent - * @param beanName name of the {@code @Configuration} class bean + * @param imported whether the given configuration class is being imported * @since 3.1.1 */ public ConfigurationClass(Class clazz, boolean imported) { @@ -119,6 +119,7 @@ final class ConfigurationClass { this.imported = imported; } + public AnnotationMetadata getMetadata() { return this.metadata; } diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java index e1676c6eb2..27ae171955 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java @@ -134,8 +134,6 @@ class ConfigurationClassBeanDefinitionReader { private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) { AnnotationMetadata metadata = configClass.getMetadata(); BeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata); - String className = metadata.getClassName(); - configBeanDef.setBeanClassName(className); if (ConfigurationClassUtils.checkConfigurationClassCandidate(configBeanDef, this.metadataReaderFactory)) { String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry); this.registry.registerBeanDefinition(configBeanName, configBeanDef); @@ -146,7 +144,7 @@ class ConfigurationClassBeanDefinitionReader { } else { this.problemReporter.error( - new InvalidConfigurationImportProblem(className, configClass.getResource(), metadata)); + new InvalidConfigurationImportProblem(metadata.getClassName(), configClass.getResource(), metadata)); } } diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java index c03aca61dd..c5a47b891a 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java @@ -17,11 +17,12 @@ package org.springframework.context.annotation; import java.io.IOException; +import java.lang.annotation.Annotation; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Map; @@ -42,6 +43,7 @@ import org.springframework.beans.factory.support.BeanDefinitionReader; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.context.ResourceLoaderAware; +import org.springframework.core.NestedIOException; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.Environment; @@ -54,7 +56,7 @@ import org.springframework.core.type.StandardAnnotationMetadata; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.AssignableTypeFilter; -import org.springframework.util.CollectionUtils; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import static org.springframework.context.annotation.MetadataUtils.*; @@ -171,45 +173,12 @@ class ConfigurationClassParser { ConfigurationClass configClass, AnnotationMetadata metadata) throws IOException { // recursively process any member (nested) classes first - for (String memberClassName : metadata.getMemberClassNames()) { - MetadataReader reader = this.metadataReaderFactory.getMetadataReader(memberClassName); - AnnotationMetadata memberClassMetadata = reader.getAnnotationMetadata(); - if (ConfigurationClassUtils.isConfigurationCandidate(memberClassMetadata)) { - processConfigurationClass(new ConfigurationClass(reader, true)); - } - } + processMemberClasses(metadata); // process any @PropertySource annotations - AnnotationAttributes propertySource = - attributesFor(metadata, org.springframework.context.annotation.PropertySource.class); + AnnotationAttributes propertySource = attributesFor(metadata, org.springframework.context.annotation.PropertySource.class); if (propertySource != null) { - String name = propertySource.getString("name"); - String[] locations = propertySource.getStringArray("value"); - int nLocations = locations.length; - if (nLocations == 0) { - throw new IllegalArgumentException("At least one @PropertySource(value) location is required"); - } - for (int i = 0; i < nLocations; i++) { - locations[i] = this.environment.resolveRequiredPlaceholders(locations[i]); - } - ClassLoader classLoader = this.resourceLoader.getClassLoader(); - if (!StringUtils.hasText(name)) { - for (String location : locations) { - this.propertySources.push(new ResourcePropertySource(location, classLoader)); - } - } - else { - if (nLocations == 1) { - this.propertySources.push(new ResourcePropertySource(name, locations[0], classLoader)); - } - else { - CompositePropertySource ps = new CompositePropertySource(name); - for (String location : locations) { - ps.addPropertySource(new ResourcePropertySource(location, classLoader)); - } - this.propertySources.push(ps); - } - } + processPropertySource(propertySource); } // process any @ComponentScan annotions @@ -228,9 +197,12 @@ class ConfigurationClassParser { } // process any @Import annotations - Set imports = getImports(metadata.getClassName(), null, new HashSet()); - if (!CollectionUtils.isEmpty(imports)) { - processImport(configClass, imports.toArray(new String[imports.size()]), true); + + Set imports = new LinkedHashSet(); + Set visited = new LinkedHashSet(); + collectImports(metadata, imports, visited); + if (!imports.isEmpty()) { + processImport(configClass, imports, true); } // process any @ImportResource annotations @@ -279,6 +251,65 @@ class ConfigurationClassParser { return null; } + /** + * Register member (nested) classes that happen to be configuration classes themselves. + * @param metadata the metadata representation of the containing class + * @throws IOException if there is any problem reading metadata from a member class + */ + private void processMemberClasses(AnnotationMetadata metadata) throws IOException { + if (metadata instanceof StandardAnnotationMetadata) { + for (Class memberClass : ((StandardAnnotationMetadata) metadata).getIntrospectedClass().getDeclaredClasses()) { + if (ConfigurationClassUtils.isConfigurationCandidate(new StandardAnnotationMetadata(memberClass))) { + processConfigurationClass(new ConfigurationClass(memberClass, true)); + } + } + } + else { + for (String memberClassName : metadata.getMemberClassNames()) { + MetadataReader reader = this.metadataReaderFactory.getMetadataReader(memberClassName); + AnnotationMetadata memberClassMetadata = reader.getAnnotationMetadata(); + if (ConfigurationClassUtils.isConfigurationCandidate(memberClassMetadata)) { + processConfigurationClass(new ConfigurationClass(reader, true)); + } + } + } + } + + /** + * Process the given @PropertySource annotation metadata. + * @param propertySource metadata for the @PropertySource annotation found + * @throws IOException if loading a property source failed + */ + private void processPropertySource(AnnotationAttributes propertySource) throws IOException { + String name = propertySource.getString("name"); + String[] locations = propertySource.getStringArray("value"); + int nLocations = locations.length; + if (nLocations == 0) { + throw new IllegalArgumentException("At least one @PropertySource(value) location is required"); + } + for (int i = 0; i < nLocations; i++) { + locations[i] = this.environment.resolveRequiredPlaceholders(locations[i]); + } + ClassLoader classLoader = this.resourceLoader.getClassLoader(); + if (!StringUtils.hasText(name)) { + for (String location : locations) { + this.propertySources.push(new ResourcePropertySource(location, classLoader)); + } + } + else { + if (nLocations == 1) { + this.propertySources.push(new ResourcePropertySource(name, locations[0], classLoader)); + } + else { + CompositePropertySource ps = new CompositePropertySource(name); + for (String location : locations) { + ps.addPropertySource(new ResourcePropertySource(location, classLoader)); + } + this.propertySources.push(ps); + } + } + } + /** * Recursively collect all declared {@code @Import} values. Unlike most * meta-annotations it is valid to have several {@code @Import}s declared with @@ -287,69 +318,99 @@ class ConfigurationClassParser { *

For example, it is common for a {@code @Configuration} class to declare direct * {@code @Import}s in addition to meta-imports originating from an {@code @Enable} * annotation. - * @param className the class name to search - * @param imports the imports collected so far or {@code null} - * @param visited used to track visited classes to prevent infinite recursion (must not be null) - * @return a set of all {@link Import#value() import values} or {@code null} + * @param metadata the metadata representation of the class to search + * @param imports the imports collected so far + * @param visited used to track visited classes to prevent infinite recursion * @throws IOException if there is any problem reading metadata from the named class */ - private Set getImports(String className, Set imports, Set visited) throws IOException { - if (visited.add(className) && !className.startsWith("java")) { - AnnotationMetadata metadata = metadataReaderFactory.getMetadataReader(className).getAnnotationMetadata(); - for (String annotationType : metadata.getAnnotationTypes()) { - imports = getImports(annotationType, imports, visited); + private void collectImports(AnnotationMetadata metadata, Set imports, Set visited) throws IOException { + String className = metadata.getClassName(); + if (visited.add(className)) { + if (metadata instanceof StandardAnnotationMetadata) { + StandardAnnotationMetadata stdMetadata = (StandardAnnotationMetadata) metadata; + for (Annotation ann : stdMetadata.getIntrospectedClass().getAnnotations()) { + if (!ann.annotationType().getName().startsWith("java") && !(ann instanceof Import)) { + collectImports(new StandardAnnotationMetadata(ann.annotationType()), imports, visited); + } + } + Map attributes = stdMetadata.getAnnotationAttributes(Import.class.getName(), false); + if (attributes != null) { + Class[] value = (Class[]) attributes.get("value"); + if (!ObjectUtils.isEmpty(value)) { + imports.addAll(Arrays.asList(value)); + } + } } - Map attributes = metadata.getAnnotationAttributes(Import.class.getName(), true); - if (attributes != null) { - String[] value = (String[]) attributes.get("value"); - if (value != null && value.length > 0) { - imports = (imports == null ? new LinkedHashSet() : imports); - imports.addAll(Arrays.asList(value)); + else { + for (String annotationType : metadata.getAnnotationTypes()) { + if (!className.startsWith("java") && !className.equals(Import.class.getName())) { + try { + collectImports( + new StandardAnnotationMetadata(this.resourceLoader.getClassLoader().loadClass(annotationType)), + imports, visited); + } + catch (ClassNotFoundException ex) { + // + } + } + } + Map attributes = metadata.getAnnotationAttributes(Import.class.getName(), true); + if (attributes != null) { + String[] value = (String[]) attributes.get("value"); + if (!ObjectUtils.isEmpty(value)) { + imports.addAll(Arrays.asList(value)); + } } } } - return imports; } - private void processImport(ConfigurationClass configClass, String[] classesToImport, boolean checkForCircularImports) throws IOException { + private void processImport(ConfigurationClass configClass, Collection classesToImport, boolean checkForCircularImports) throws IOException { if (checkForCircularImports && this.importStack.contains(configClass)) { this.problemReporter.error(new CircularImportProblem(configClass, this.importStack, configClass.getMetadata())); } else { this.importStack.push(configClass); AnnotationMetadata importingClassMetadata = configClass.getMetadata(); - for (String candidate : classesToImport) { - MetadataReader reader = this.metadataReaderFactory.getMetadataReader(candidate); - if (new AssignableTypeFilter(ImportSelector.class).match(reader, this.metadataReaderFactory)) { - // the candidate class is an ImportSelector -> delegate to it to determine imports - try { - ImportSelector selector = BeanUtils.instantiateClass( - this.resourceLoader.getClassLoader().loadClass(candidate), ImportSelector.class); - processImport(configClass, selector.selectImports(importingClassMetadata), false); + try { + for (Object candidate : classesToImport) { + Object candidateToCheck = (candidate instanceof Class ? (Class) candidate : this.metadataReaderFactory.getMetadataReader((String) candidate)); + if (checkAssignability(ImportSelector.class, candidateToCheck)) { + // the candidate class is an ImportSelector -> delegate to it to determine imports + Class candidateClass = (candidate instanceof Class ? (Class) candidate : this.resourceLoader.getClassLoader().loadClass((String) candidate)); + ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class); + processImport(configClass, Arrays.asList(selector.selectImports(importingClassMetadata)), false); } - catch (ClassNotFoundException ex) { - throw new IllegalStateException(ex); - } - } - else if (new AssignableTypeFilter(ImportBeanDefinitionRegistrar.class).match(reader, this.metadataReaderFactory)) { - // the candidate class is an ImportBeanDefinitionRegistrar -> delegate to it to register additional bean definitions - try { - ImportBeanDefinitionRegistrar registrar = BeanUtils.instantiateClass( - this.resourceLoader.getClassLoader().loadClass(candidate), ImportBeanDefinitionRegistrar.class); + else if (checkAssignability(ImportBeanDefinitionRegistrar.class, candidateToCheck)) { + // the candidate class is an ImportBeanDefinitionRegistrar -> delegate to it to register additional bean definitions + Class candidateClass = (candidate instanceof Class ? (Class) candidate : this.resourceLoader.getClassLoader().loadClass((String) candidate)); + ImportBeanDefinitionRegistrar registrar = BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class); invokeAwareMethods(registrar); - registrar.registerBeanDefinitions(importingClassMetadata, registry); + registrar.registerBeanDefinitions(importingClassMetadata, this.registry); } - catch (ClassNotFoundException ex) { - throw new IllegalStateException(ex); + else { + // candidate class not an ImportSelector or ImportBeanDefinitionRegistrar -> process it as a @Configuration class + this.importStack.registerImport(importingClassMetadata.getClassName(), (candidate instanceof Class ? ((Class) candidate).getName() : (String) candidate)); + processConfigurationClass(candidateToCheck instanceof Class ? new ConfigurationClass((Class) candidateToCheck, true) : + new ConfigurationClass((MetadataReader) candidateToCheck, true)); } } - else { - // the candidate class not an ImportSelector or ImportBeanDefinitionRegistrar -> process it as a @Configuration class - this.importStack.registerImport(importingClassMetadata.getClassName(), candidate); - processConfigurationClass(new ConfigurationClass(reader, true)); - } } - this.importStack.pop(); + catch (ClassNotFoundException ex) { + throw new NestedIOException("Failed to load import candidate class", ex); + } + finally { + this.importStack.pop(); + } + } + } + + private boolean checkAssignability(Class clazz, Object candidate) throws IOException { + if (candidate instanceof Class) { + return clazz.isAssignableFrom((Class) candidate); + } + else { + return new AssignableTypeFilter(clazz).match((MetadataReader) candidate, this.metadataReaderFactory); } } diff --git a/spring-context/src/test/java/org/springframework/context/annotation/configuration/ImportedConfigurationClassEnhancementTests.java b/spring-context/src/test/java/org/springframework/context/annotation/configuration/ImportedConfigurationClassEnhancementTests.java index e895a207c3..2bc75f1754 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/configuration/ImportedConfigurationClassEnhancementTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/configuration/ImportedConfigurationClassEnhancementTests.java @@ -79,7 +79,7 @@ public class ImportedConfigurationClassEnhancementTests { @Test(expected=BeanDefinitionParsingException.class) - public void importingAnNonConfigurationClassCausesIllegalArgumentException() { + public void importingNonConfigurationClassCausesBeanDefinitionParsingException() { new AnnotationConfigApplicationContext(ConfigThatImportsNonConfigClass.class); } } @@ -103,5 +103,5 @@ class ConfigThatDoesImport extends Config { } class ConfigThatDoesNotImport extends Config { } @Configuration -@Import(Void.class) +@Import(TestBean.class) class ConfigThatImportsNonConfigClass { } \ No newline at end of file diff --git a/spring-core/src/main/java/org/springframework/core/LocalVariableTableParameterNameDiscoverer.java b/spring-core/src/main/java/org/springframework/core/LocalVariableTableParameterNameDiscoverer.java index 3cab216bf0..d846d4fdae 100644 --- a/spring-core/src/main/java/org/springframework/core/LocalVariableTableParameterNameDiscoverer.java +++ b/spring-core/src/main/java/org/springframework/core/LocalVariableTableParameterNameDiscoverer.java @@ -114,8 +114,15 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD } catch (IOException ex) { if (logger.isDebugEnabled()) { - logger.debug("Exception thrown while reading '.class' file for class [" + clazz - + "] - unable to determine constructors/methods parameter names", ex); + logger.debug("Exception thrown while reading '.class' file for class [" + clazz + + "] - unable to determine constructors/methods parameter names", ex); + } + } + catch (IllegalArgumentException ex) { + if (logger.isDebugEnabled()) { + logger.debug("ASM ClassReader failed to parse class file [" + clazz + + "], probably due to a new Java class file version that isn't supported yet " + + "- unable to determine constructors/methods parameter names", ex); } } finally { diff --git a/spring-core/src/main/java/org/springframework/core/type/StandardAnnotationMetadata.java b/spring-core/src/main/java/org/springframework/core/type/StandardAnnotationMetadata.java index 1e5d00a9ca..37473c5a77 100644 --- a/spring-core/src/main/java/org/springframework/core/type/StandardAnnotationMetadata.java +++ b/spring-core/src/main/java/org/springframework/core/type/StandardAnnotationMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -145,6 +145,8 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements return AnnotationUtils.getAnnotationAttributes( ann, classValuesAsString, this.nestedAnnotationsAsMap); } + } + for (Annotation ann : anns) { for (Annotation metaAnn : ann.annotationType().getAnnotations()) { if (metaAnn.annotationType().getName().equals(annotationType)) { return AnnotationUtils.getAnnotationAttributes( diff --git a/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java b/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java index 97a4897f81..982534a379 100644 --- a/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java +++ b/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -105,19 +105,11 @@ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor } public AnnotationAttributes getAnnotationAttributes(String annotationType, boolean classValuesAsString) { - return getAnnotationAttributes(annotationType, classValuesAsString, false); - } - - public AnnotationAttributes getAnnotationAttributes( - String annotationType, boolean classValuesAsString, boolean nestedAttributesAsMap) { - AnnotationAttributes raw = this.attributeMap.get(annotationType); - return convertClassValues(raw, classValuesAsString, nestedAttributesAsMap); + return convertClassValues(raw, classValuesAsString); } - private AnnotationAttributes convertClassValues( - AnnotationAttributes original, boolean classValuesAsString, boolean nestedAttributesAsMap) { - + private AnnotationAttributes convertClassValues(AnnotationAttributes original, boolean classValuesAsString) { if (original == null) { return null; } @@ -126,12 +118,12 @@ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor try { Object value = entry.getValue(); if (value instanceof AnnotationAttributes) { - value = convertClassValues((AnnotationAttributes)value, classValuesAsString, nestedAttributesAsMap); + value = convertClassValues((AnnotationAttributes) value, classValuesAsString); } else if (value instanceof AnnotationAttributes[]) { AnnotationAttributes[] values = (AnnotationAttributes[])value; for (int i = 0; i < values.length; i++) { - values[i] = convertClassValues(values[i], classValuesAsString, nestedAttributesAsMap); + values[i] = convertClassValues(values[i], classValuesAsString); } } else if (value instanceof Type) { @@ -182,4 +174,5 @@ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor annotatedMethods.addAll(list); return annotatedMethods; } + } diff --git a/spring-core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReader.java b/spring-core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReader.java index af2d4c62d8..36c495e542 100644 --- a/spring-core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReader.java +++ b/spring-core/src/main/java/org/springframework/core/type/classreading/SimpleMetadataReader.java @@ -64,7 +64,7 @@ final class SimpleMetadataReader implements MetadataReader { classReader.accept(visitor, ClassReader.SKIP_DEBUG); this.annotationMetadata = visitor; - // (since AnnotationMetadataReader extends ClassMetadataReadingVisitor) + // (since AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor) this.classMetadata = visitor; this.resource = resource; } diff --git a/spring-tx/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementTests.java b/spring-tx/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementTests.java index 5c11e26d5d..896170e048 100644 --- a/spring-tx/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementTests.java +++ b/spring-tx/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementTests.java @@ -16,13 +16,10 @@ package org.springframework.transaction.annotation; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; - import java.util.Map; import org.junit.Test; + import org.springframework.aop.support.AopUtils; import org.springframework.context.annotation.AdviceMode; import org.springframework.context.annotation.AnnotationConfigApplicationContext; @@ -33,6 +30,9 @@ import org.springframework.tests.transaction.CallCountingTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.AnnotationTransactionNamespaceHandlerTests.TransactionalTestBean; +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + /** * Tests demonstrating use of @EnableTransactionManagement @Configuration classes. * @@ -84,9 +84,9 @@ public class EnableTransactionManagementTests { new AnnotationConfigApplicationContext(EnableAspectJTxConfig.class, TxManagerConfig.class); fail("should have thrown CNFE when trying to load AnnotationTransactionAspect. " + "Do you actually have org.springframework.aspects on the classpath?"); - } catch (Exception ex) { - System.out.println(ex); - assertThat(ex.getMessage().endsWith("AspectJTransactionManagementConfiguration.class] cannot be opened because it does not exist"), is(true)); + } + catch (Exception ex) { + assertThat(ex.getMessage().contains("AspectJTransactionManagementConfiguration"), is(true)); } } diff --git a/src/test/java/org/springframework/cache/annotation/EnableCachingIntegrationTests.java b/src/test/java/org/springframework/cache/annotation/EnableCachingIntegrationTests.java index 0f0fc64ac8..39d221b78e 100644 --- a/src/test/java/org/springframework/cache/annotation/EnableCachingIntegrationTests.java +++ b/src/test/java/org/springframework/cache/annotation/EnableCachingIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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,14 +16,11 @@ package org.springframework.cache.annotation; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; - import java.util.Collections; import java.util.List; import org.junit.Test; + import org.springframework.aop.Advisor; import org.springframework.aop.framework.Advised; import org.springframework.aop.support.AopUtils; @@ -36,6 +33,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Repository; +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + /** * Integration tests for the @EnableCaching annotation. * @@ -60,11 +60,12 @@ public class EnableCachingIntegrationTests { ctx.register(Config.class, AspectJCacheConfig.class); try { ctx.refresh(); - } catch (Exception ex) { + } + catch (Exception ex) { // this test is a bit fragile, but gets the job done, proving that an // attempt was made to look up the AJ aspect. It's due to classpath issues // in .integration-tests that it's not found. - assertTrue(ex.getMessage().endsWith("AspectJCachingConfiguration.class] cannot be opened because it does not exist")); + assertTrue(ex.getMessage().contains("AspectJCachingConfiguration")); } } diff --git a/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementIntegrationTests.java b/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementIntegrationTests.java index 54511e7e7b..b5eb2f8e1b 100644 --- a/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementIntegrationTests.java +++ b/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementIntegrationTests.java @@ -115,11 +115,12 @@ public class EnableTransactionManagementIntegrationTests { ctx.register(Config.class, AspectJTxConfig.class); try { ctx.refresh(); - } catch (Exception ex) { + } + catch (Exception ex) { // this test is a bit fragile, but gets the job done, proving that an // attempt was made to look up the AJ aspect. It's due to classpath issues // in .integration-tests that it's not found. - assertTrue(ex.getMessage().endsWith("AspectJTransactionManagementConfiguration.class] cannot be opened because it does not exist")); + assertTrue(ex.getMessage().contains("AspectJTransactionManagementConfiguration")); } } -- GitLab