Configuration class parsing reuses metadata from AnnotatedBeanDefinition as far as possible
Issue: SPR-12394
This commit is contained in:
@@ -68,11 +68,10 @@ final class ConfigurationClass {
|
||||
* Create a new {@link ConfigurationClass} with the given name.
|
||||
* @param metadataReader reader used to parse the underlying {@link Class}
|
||||
* @param beanName must not be {@code null}
|
||||
* @throws IllegalArgumentException if beanName is null (as of Spring 3.1.1)
|
||||
* @see ConfigurationClass#ConfigurationClass(Class, ConfigurationClass)
|
||||
*/
|
||||
public ConfigurationClass(MetadataReader metadataReader, String beanName) {
|
||||
Assert.hasText(beanName, "bean name must not be null");
|
||||
Assert.hasText(beanName, "Bean name must not be null");
|
||||
this.metadata = metadataReader.getAnnotationMetadata();
|
||||
this.resource = metadataReader.getResource();
|
||||
this.beanName = beanName;
|
||||
@@ -96,7 +95,6 @@ final class ConfigurationClass {
|
||||
* Create a new {@link ConfigurationClass} with the given name.
|
||||
* @param clazz the underlying {@link Class} to represent
|
||||
* @param beanName name of the {@code @Configuration} class bean
|
||||
* @throws IllegalArgumentException if beanName is null (as of Spring 3.1.1)
|
||||
* @see ConfigurationClass#ConfigurationClass(Class, ConfigurationClass)
|
||||
*/
|
||||
public ConfigurationClass(Class<?> clazz, String beanName) {
|
||||
@@ -120,6 +118,19 @@ final class ConfigurationClass {
|
||||
this.importedBy.add(importedBy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link ConfigurationClass} with the given name.
|
||||
* @param metadata the metadata for the underlying class to represent
|
||||
* @param beanName name of the {@code @Configuration} class bean
|
||||
* @see ConfigurationClass#ConfigurationClass(Class, ConfigurationClass)
|
||||
*/
|
||||
public ConfigurationClass(AnnotationMetadata metadata, String beanName) {
|
||||
Assert.hasText(beanName, "Bean name must not be null");
|
||||
this.metadata = metadata;
|
||||
this.resource = new DescriptiveResource(metadata.getClassName());
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
|
||||
public AnnotationMetadata getMetadata() {
|
||||
return this.metadata;
|
||||
|
||||
@@ -41,6 +41,7 @@ import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
@@ -158,7 +159,10 @@ class ConfigurationClassParser {
|
||||
for (BeanDefinitionHolder holder : configCandidates) {
|
||||
BeanDefinition bd = holder.getBeanDefinition();
|
||||
try {
|
||||
if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
|
||||
if (bd instanceof AnnotatedBeanDefinition) {
|
||||
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
|
||||
}
|
||||
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
|
||||
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
|
||||
}
|
||||
else {
|
||||
@@ -169,32 +173,26 @@ class ConfigurationClassParser {
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new BeanDefinitionStoreException("Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
|
||||
throw new BeanDefinitionStoreException(
|
||||
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
|
||||
}
|
||||
}
|
||||
processDeferredImportSelectors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the specified {@link Configuration @Configuration} class.
|
||||
* @param className the name of the class to parse
|
||||
* @param beanName may be null, but if populated represents the bean id
|
||||
* (assumes that this configuration class was configured via XML)
|
||||
*/
|
||||
protected final void parse(String className, String beanName) throws IOException {
|
||||
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
|
||||
processConfigurationClass(new ConfigurationClass(reader, beanName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the specified {@link Configuration @Configuration} class.
|
||||
* @param clazz the Class to parse
|
||||
* @param beanName must not be null (as of Spring 3.1.1)
|
||||
*/
|
||||
protected final void parse(Class<?> clazz, String beanName) throws IOException {
|
||||
processConfigurationClass(new ConfigurationClass(clazz, beanName));
|
||||
}
|
||||
|
||||
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
|
||||
processConfigurationClass(new ConfigurationClass(metadata, beanName));
|
||||
}
|
||||
|
||||
|
||||
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
|
||||
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.util.Set;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.core.Conventions;
|
||||
@@ -70,41 +71,47 @@ abstract class ConfigurationClassUtils {
|
||||
* @return whether the candidate qualifies as (any kind of) configuration class
|
||||
*/
|
||||
public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
|
||||
AnnotationMetadata metadata = null;
|
||||
String className = beanDef.getBeanClassName();
|
||||
if (className == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check already loaded Class if present...
|
||||
// since we possibly can't even load the class file for this Class.
|
||||
if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
|
||||
AnnotationMetadata metadata;
|
||||
if (beanDef instanceof AnnotatedBeanDefinition &&
|
||||
className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
|
||||
// Can reuse the pre-parsed metadata from the given BeanDefinition...
|
||||
metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
|
||||
}
|
||||
else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
|
||||
// Check already loaded Class if present...
|
||||
// since we possibly can't even load the class file for this Class.
|
||||
Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
|
||||
metadata = new StandardAnnotationMetadata(beanClass, true);
|
||||
}
|
||||
else {
|
||||
String className = beanDef.getBeanClassName();
|
||||
if (className != null) {
|
||||
try {
|
||||
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
|
||||
metadata = metadataReader.getAnnotationMetadata();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not find class file for introspecting factory methods: " + className, ex);
|
||||
}
|
||||
return false;
|
||||
try {
|
||||
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
|
||||
metadata = metadataReader.getAnnotationMetadata();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not find class file for introspecting configuration annotations: " + className, ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (metadata != null) {
|
||||
if (isFullConfigurationCandidate(metadata)) {
|
||||
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
|
||||
return true;
|
||||
}
|
||||
else if (isLiteConfigurationCandidate(metadata)) {
|
||||
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
|
||||
return true;
|
||||
}
|
||||
if (isFullConfigurationCandidate(metadata)) {
|
||||
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
|
||||
return true;
|
||||
}
|
||||
else if (isLiteConfigurationCandidate(metadata)) {
|
||||
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user