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
This commit is contained in:
parent
34bcdcfe85
commit
d3a4068768
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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.
|
* allowing for ASM-based processing and avoidance of early loading of the bean class.
|
||||||
* Note that this constructor is functionally equivalent to
|
* Note that this constructor is functionally equivalent to
|
||||||
* {@link org.springframework.context.annotation.ScannedGenericBeanDefinition
|
* {@link org.springframework.context.annotation.ScannedGenericBeanDefinition
|
||||||
* ScannedGenericBeanDefinition}, however the semantics of the latter indicate that
|
* ScannedGenericBeanDefinition}, however the semantics of the latter indicate that a
|
||||||
* a bean was discovered specifically via component-scanning as opposed to other
|
* bean was discovered specifically via component-scanning as opposed to other means.
|
||||||
* means.
|
|
||||||
* @param metadata the annotation metadata for the bean class in question
|
* @param metadata the annotation metadata for the bean class in question
|
||||||
* @since 3.1.1
|
* @since 3.1.1
|
||||||
*/
|
*/
|
||||||
public AnnotatedGenericBeanDefinition(AnnotationMetadata metadata) {
|
public AnnotatedGenericBeanDefinition(AnnotationMetadata metadata) {
|
||||||
Assert.notNull(metadata, "AnnotationMetadata must not be null");
|
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;
|
this.metadata = metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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
|
* using the {@link Import} annotation or automatically processed as a nested
|
||||||
* configuration class (if imported is {@code true}).
|
* configuration class (if imported is {@code true}).
|
||||||
* @param metadataReader reader used to parse the underlying {@link Class}
|
* @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
|
* @since 3.1.1
|
||||||
*/
|
*/
|
||||||
public ConfigurationClass(MetadataReader metadataReader, boolean imported) {
|
public ConfigurationClass(MetadataReader metadataReader, boolean imported) {
|
||||||
|
@ -110,7 +110,7 @@ final class ConfigurationClass {
|
||||||
* using the {@link Import} annotation or automatically processed as a nested
|
* using the {@link Import} annotation or automatically processed as a nested
|
||||||
* configuration class (if imported is {@code true}).
|
* configuration class (if imported is {@code true}).
|
||||||
* @param clazz the underlying {@link Class} to represent
|
* @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
|
* @since 3.1.1
|
||||||
*/
|
*/
|
||||||
public ConfigurationClass(Class<?> clazz, boolean imported) {
|
public ConfigurationClass(Class<?> clazz, boolean imported) {
|
||||||
|
@ -119,6 +119,7 @@ final class ConfigurationClass {
|
||||||
this.imported = imported;
|
this.imported = imported;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public AnnotationMetadata getMetadata() {
|
public AnnotationMetadata getMetadata() {
|
||||||
return this.metadata;
|
return this.metadata;
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,8 +134,6 @@ class ConfigurationClassBeanDefinitionReader {
|
||||||
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
|
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
|
||||||
AnnotationMetadata metadata = configClass.getMetadata();
|
AnnotationMetadata metadata = configClass.getMetadata();
|
||||||
BeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
|
BeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
|
||||||
String className = metadata.getClassName();
|
|
||||||
configBeanDef.setBeanClassName(className);
|
|
||||||
if (ConfigurationClassUtils.checkConfigurationClassCandidate(configBeanDef, this.metadataReaderFactory)) {
|
if (ConfigurationClassUtils.checkConfigurationClassCandidate(configBeanDef, this.metadataReaderFactory)) {
|
||||||
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
|
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
|
||||||
this.registry.registerBeanDefinition(configBeanName, configBeanDef);
|
this.registry.registerBeanDefinition(configBeanName, configBeanDef);
|
||||||
|
@ -146,7 +144,7 @@ class ConfigurationClassBeanDefinitionReader {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.problemReporter.error(
|
this.problemReporter.error(
|
||||||
new InvalidConfigurationImportProblem(className, configClass.getResource(), metadata));
|
new InvalidConfigurationImportProblem(metadata.getClassName(), configClass.getResource(), metadata));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,12 @@
|
||||||
package org.springframework.context.annotation;
|
package org.springframework.context.annotation;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Map;
|
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.BeanDefinitionRegistry;
|
||||||
import org.springframework.beans.factory.support.BeanNameGenerator;
|
import org.springframework.beans.factory.support.BeanNameGenerator;
|
||||||
import org.springframework.context.ResourceLoaderAware;
|
import org.springframework.context.ResourceLoaderAware;
|
||||||
|
import org.springframework.core.NestedIOException;
|
||||||
import org.springframework.core.annotation.AnnotationAttributes;
|
import org.springframework.core.annotation.AnnotationAttributes;
|
||||||
import org.springframework.core.env.CompositePropertySource;
|
import org.springframework.core.env.CompositePropertySource;
|
||||||
import org.springframework.core.env.Environment;
|
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.MetadataReader;
|
||||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||||
import org.springframework.core.type.filter.AssignableTypeFilter;
|
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import static org.springframework.context.annotation.MetadataUtils.*;
|
import static org.springframework.context.annotation.MetadataUtils.*;
|
||||||
|
@ -171,45 +173,12 @@ class ConfigurationClassParser {
|
||||||
ConfigurationClass configClass, AnnotationMetadata metadata) throws IOException {
|
ConfigurationClass configClass, AnnotationMetadata metadata) throws IOException {
|
||||||
|
|
||||||
// recursively process any member (nested) classes first
|
// recursively process any member (nested) classes first
|
||||||
for (String memberClassName : metadata.getMemberClassNames()) {
|
processMemberClasses(metadata);
|
||||||
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(memberClassName);
|
|
||||||
AnnotationMetadata memberClassMetadata = reader.getAnnotationMetadata();
|
|
||||||
if (ConfigurationClassUtils.isConfigurationCandidate(memberClassMetadata)) {
|
|
||||||
processConfigurationClass(new ConfigurationClass(reader, true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// process any @PropertySource annotations
|
// process any @PropertySource annotations
|
||||||
AnnotationAttributes propertySource =
|
AnnotationAttributes propertySource = attributesFor(metadata, org.springframework.context.annotation.PropertySource.class);
|
||||||
attributesFor(metadata, org.springframework.context.annotation.PropertySource.class);
|
|
||||||
if (propertySource != null) {
|
if (propertySource != null) {
|
||||||
String name = propertySource.getString("name");
|
processPropertySource(propertySource);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// process any @ComponentScan annotions
|
// process any @ComponentScan annotions
|
||||||
|
@ -228,9 +197,12 @@ class ConfigurationClassParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
// process any @Import annotations
|
// process any @Import annotations
|
||||||
Set<String> imports = getImports(metadata.getClassName(), null, new HashSet<String>());
|
|
||||||
if (!CollectionUtils.isEmpty(imports)) {
|
Set<Object> imports = new LinkedHashSet<Object>();
|
||||||
processImport(configClass, imports.toArray(new String[imports.size()]), true);
|
Set<Object> visited = new LinkedHashSet<Object>();
|
||||||
|
collectImports(metadata, imports, visited);
|
||||||
|
if (!imports.isEmpty()) {
|
||||||
|
processImport(configClass, imports, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// process any @ImportResource annotations
|
// process any @ImportResource annotations
|
||||||
|
@ -279,6 +251,65 @@ class ConfigurationClassParser {
|
||||||
return null;
|
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 <code>@PropertySource</code> annotation metadata.
|
||||||
|
* @param propertySource metadata for the <code>@PropertySource</code> 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
|
* Recursively collect all declared {@code @Import} values. Unlike most
|
||||||
* meta-annotations it is valid to have several {@code @Import}s declared with
|
* meta-annotations it is valid to have several {@code @Import}s declared with
|
||||||
|
@ -287,69 +318,99 @@ class ConfigurationClassParser {
|
||||||
* <p>For example, it is common for a {@code @Configuration} class to declare direct
|
* <p>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}
|
* {@code @Import}s in addition to meta-imports originating from an {@code @Enable}
|
||||||
* annotation.
|
* annotation.
|
||||||
* @param className the class name to search
|
* @param metadata the metadata representation of the class to search
|
||||||
* @param imports the imports collected so far or {@code null}
|
* @param imports the imports collected so far
|
||||||
* @param visited used to track visited classes to prevent infinite recursion (must not be null)
|
* @param visited used to track visited classes to prevent infinite recursion
|
||||||
* @return a set of all {@link Import#value() import values} or {@code null}
|
|
||||||
* @throws IOException if there is any problem reading metadata from the named class
|
* @throws IOException if there is any problem reading metadata from the named class
|
||||||
*/
|
*/
|
||||||
private Set<String> getImports(String className, Set<String> imports, Set<String> visited) throws IOException {
|
private void collectImports(AnnotationMetadata metadata, Set<Object> imports, Set<Object> visited) throws IOException {
|
||||||
if (visited.add(className) && !className.startsWith("java")) {
|
String className = metadata.getClassName();
|
||||||
AnnotationMetadata metadata = metadataReaderFactory.getMetadataReader(className).getAnnotationMetadata();
|
if (visited.add(className)) {
|
||||||
for (String annotationType : metadata.getAnnotationTypes()) {
|
if (metadata instanceof StandardAnnotationMetadata) {
|
||||||
imports = getImports(annotationType, imports, visited);
|
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<String, Object> 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<String, Object> attributes = metadata.getAnnotationAttributes(Import.class.getName(), true);
|
else {
|
||||||
if (attributes != null) {
|
for (String annotationType : metadata.getAnnotationTypes()) {
|
||||||
String[] value = (String[]) attributes.get("value");
|
if (!className.startsWith("java") && !className.equals(Import.class.getName())) {
|
||||||
if (value != null && value.length > 0) {
|
try {
|
||||||
imports = (imports == null ? new LinkedHashSet<String>() : imports);
|
collectImports(
|
||||||
imports.addAll(Arrays.asList(value));
|
new StandardAnnotationMetadata(this.resourceLoader.getClassLoader().loadClass(annotationType)),
|
||||||
|
imports, visited);
|
||||||
|
}
|
||||||
|
catch (ClassNotFoundException ex) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Map<String, Object> 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)) {
|
if (checkForCircularImports && this.importStack.contains(configClass)) {
|
||||||
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack, configClass.getMetadata()));
|
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack, configClass.getMetadata()));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.importStack.push(configClass);
|
this.importStack.push(configClass);
|
||||||
AnnotationMetadata importingClassMetadata = configClass.getMetadata();
|
AnnotationMetadata importingClassMetadata = configClass.getMetadata();
|
||||||
for (String candidate : classesToImport) {
|
try {
|
||||||
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(candidate);
|
for (Object candidate : classesToImport) {
|
||||||
if (new AssignableTypeFilter(ImportSelector.class).match(reader, this.metadataReaderFactory)) {
|
Object candidateToCheck = (candidate instanceof Class ? (Class) candidate : this.metadataReaderFactory.getMetadataReader((String) candidate));
|
||||||
// the candidate class is an ImportSelector -> delegate to it to determine imports
|
if (checkAssignability(ImportSelector.class, candidateToCheck)) {
|
||||||
try {
|
// the candidate class is an ImportSelector -> delegate to it to determine imports
|
||||||
ImportSelector selector = BeanUtils.instantiateClass(
|
Class<?> candidateClass = (candidate instanceof Class ? (Class) candidate : this.resourceLoader.getClassLoader().loadClass((String) candidate));
|
||||||
this.resourceLoader.getClassLoader().loadClass(candidate), ImportSelector.class);
|
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
|
||||||
processImport(configClass, selector.selectImports(importingClassMetadata), false);
|
processImport(configClass, Arrays.asList(selector.selectImports(importingClassMetadata)), false);
|
||||||
}
|
}
|
||||||
catch (ClassNotFoundException ex) {
|
else if (checkAssignability(ImportBeanDefinitionRegistrar.class, candidateToCheck)) {
|
||||||
throw new IllegalStateException(ex);
|
// 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);
|
||||||
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);
|
|
||||||
invokeAwareMethods(registrar);
|
invokeAwareMethods(registrar);
|
||||||
registrar.registerBeanDefinitions(importingClassMetadata, registry);
|
registrar.registerBeanDefinitions(importingClassMetadata, this.registry);
|
||||||
}
|
}
|
||||||
catch (ClassNotFoundException ex) {
|
else {
|
||||||
throw new IllegalStateException(ex);
|
// 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ public class ImportedConfigurationClassEnhancementTests {
|
||||||
|
|
||||||
|
|
||||||
@Test(expected=BeanDefinitionParsingException.class)
|
@Test(expected=BeanDefinitionParsingException.class)
|
||||||
public void importingAnNonConfigurationClassCausesIllegalArgumentException() {
|
public void importingNonConfigurationClassCausesBeanDefinitionParsingException() {
|
||||||
new AnnotationConfigApplicationContext(ConfigThatImportsNonConfigClass.class);
|
new AnnotationConfigApplicationContext(ConfigThatImportsNonConfigClass.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,5 +103,5 @@ class ConfigThatDoesImport extends Config { }
|
||||||
class ConfigThatDoesNotImport extends Config { }
|
class ConfigThatDoesNotImport extends Config { }
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@Import(Void.class)
|
@Import(TestBean.class)
|
||||||
class ConfigThatImportsNonConfigClass { }
|
class ConfigThatImportsNonConfigClass { }
|
|
@ -114,8 +114,15 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
|
||||||
}
|
}
|
||||||
catch (IOException ex) {
|
catch (IOException ex) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Exception thrown while reading '.class' file for class [" + clazz
|
logger.debug("Exception thrown while reading '.class' file for class [" + clazz +
|
||||||
+ "] - unable to determine constructors/methods parameter names", ex);
|
"] - 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 {
|
finally {
|
||||||
|
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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(
|
return AnnotationUtils.getAnnotationAttributes(
|
||||||
ann, classValuesAsString, this.nestedAnnotationsAsMap);
|
ann, classValuesAsString, this.nestedAnnotationsAsMap);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
for (Annotation ann : anns) {
|
||||||
for (Annotation metaAnn : ann.annotationType().getAnnotations()) {
|
for (Annotation metaAnn : ann.annotationType().getAnnotations()) {
|
||||||
if (metaAnn.annotationType().getName().equals(annotationType)) {
|
if (metaAnn.annotationType().getName().equals(annotationType)) {
|
||||||
return AnnotationUtils.getAnnotationAttributes(
|
return AnnotationUtils.getAnnotationAttributes(
|
||||||
|
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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) {
|
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);
|
AnnotationAttributes raw = this.attributeMap.get(annotationType);
|
||||||
return convertClassValues(raw, classValuesAsString, nestedAttributesAsMap);
|
return convertClassValues(raw, classValuesAsString);
|
||||||
}
|
}
|
||||||
|
|
||||||
private AnnotationAttributes convertClassValues(
|
private AnnotationAttributes convertClassValues(AnnotationAttributes original, boolean classValuesAsString) {
|
||||||
AnnotationAttributes original, boolean classValuesAsString, boolean nestedAttributesAsMap) {
|
|
||||||
|
|
||||||
if (original == null) {
|
if (original == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -126,12 +118,12 @@ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor
|
||||||
try {
|
try {
|
||||||
Object value = entry.getValue();
|
Object value = entry.getValue();
|
||||||
if (value instanceof AnnotationAttributes) {
|
if (value instanceof AnnotationAttributes) {
|
||||||
value = convertClassValues((AnnotationAttributes)value, classValuesAsString, nestedAttributesAsMap);
|
value = convertClassValues((AnnotationAttributes) value, classValuesAsString);
|
||||||
}
|
}
|
||||||
else if (value instanceof AnnotationAttributes[]) {
|
else if (value instanceof AnnotationAttributes[]) {
|
||||||
AnnotationAttributes[] values = (AnnotationAttributes[])value;
|
AnnotationAttributes[] values = (AnnotationAttributes[])value;
|
||||||
for (int i = 0; i < values.length; i++) {
|
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) {
|
else if (value instanceof Type) {
|
||||||
|
@ -182,4 +174,5 @@ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor
|
||||||
annotatedMethods.addAll(list);
|
annotatedMethods.addAll(list);
|
||||||
return annotatedMethods;
|
return annotatedMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ final class SimpleMetadataReader implements MetadataReader {
|
||||||
classReader.accept(visitor, ClassReader.SKIP_DEBUG);
|
classReader.accept(visitor, ClassReader.SKIP_DEBUG);
|
||||||
|
|
||||||
this.annotationMetadata = visitor;
|
this.annotationMetadata = visitor;
|
||||||
// (since AnnotationMetadataReader extends ClassMetadataReadingVisitor)
|
// (since AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor)
|
||||||
this.classMetadata = visitor;
|
this.classMetadata = visitor;
|
||||||
this.resource = resource;
|
this.resource = resource;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,10 @@
|
||||||
|
|
||||||
package org.springframework.transaction.annotation;
|
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 java.util.Map;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.aop.support.AopUtils;
|
import org.springframework.aop.support.AopUtils;
|
||||||
import org.springframework.context.annotation.AdviceMode;
|
import org.springframework.context.annotation.AdviceMode;
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
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.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.annotation.AnnotationTransactionNamespaceHandlerTests.TransactionalTestBean;
|
import org.springframework.transaction.annotation.AnnotationTransactionNamespaceHandlerTests.TransactionalTestBean;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.*;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests demonstrating use of @EnableTransactionManagement @Configuration classes.
|
* Tests demonstrating use of @EnableTransactionManagement @Configuration classes.
|
||||||
*
|
*
|
||||||
|
@ -84,9 +84,9 @@ public class EnableTransactionManagementTests {
|
||||||
new AnnotationConfigApplicationContext(EnableAspectJTxConfig.class, TxManagerConfig.class);
|
new AnnotationConfigApplicationContext(EnableAspectJTxConfig.class, TxManagerConfig.class);
|
||||||
fail("should have thrown CNFE when trying to load AnnotationTransactionAspect. " +
|
fail("should have thrown CNFE when trying to load AnnotationTransactionAspect. " +
|
||||||
"Do you actually have org.springframework.aspects on the classpath?");
|
"Do you actually have org.springframework.aspects on the classpath?");
|
||||||
} catch (Exception ex) {
|
}
|
||||||
System.out.println(ex);
|
catch (Exception ex) {
|
||||||
assertThat(ex.getMessage().endsWith("AspectJTransactionManagementConfiguration.class] cannot be opened because it does not exist"), is(true));
|
assertThat(ex.getMessage().contains("AspectJTransactionManagementConfiguration"), is(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,14 +16,11 @@
|
||||||
|
|
||||||
package org.springframework.cache.annotation;
|
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.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.aop.Advisor;
|
import org.springframework.aop.Advisor;
|
||||||
import org.springframework.aop.framework.Advised;
|
import org.springframework.aop.framework.Advised;
|
||||||
import org.springframework.aop.support.AopUtils;
|
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.context.annotation.Configuration;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.*;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Integration tests for the @EnableCaching annotation.
|
* Integration tests for the @EnableCaching annotation.
|
||||||
*
|
*
|
||||||
|
@ -60,11 +60,12 @@ public class EnableCachingIntegrationTests {
|
||||||
ctx.register(Config.class, AspectJCacheConfig.class);
|
ctx.register(Config.class, AspectJCacheConfig.class);
|
||||||
try {
|
try {
|
||||||
ctx.refresh();
|
ctx.refresh();
|
||||||
} catch (Exception ex) {
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
// this test is a bit fragile, but gets the job done, proving that an
|
// 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
|
// attempt was made to look up the AJ aspect. It's due to classpath issues
|
||||||
// in .integration-tests that it's not found.
|
// 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"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,11 +115,12 @@ public class EnableTransactionManagementIntegrationTests {
|
||||||
ctx.register(Config.class, AspectJTxConfig.class);
|
ctx.register(Config.class, AspectJTxConfig.class);
|
||||||
try {
|
try {
|
||||||
ctx.refresh();
|
ctx.refresh();
|
||||||
} catch (Exception ex) {
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
// this test is a bit fragile, but gets the job done, proving that an
|
// 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
|
// attempt was made to look up the AJ aspect. It's due to classpath issues
|
||||||
// in .integration-tests that it's not found.
|
// 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"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue