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.
|
* Create a new {@link ConfigurationClass} with the given name.
|
||||||
* @param metadataReader reader used to parse the underlying {@link Class}
|
* @param metadataReader reader used to parse the underlying {@link Class}
|
||||||
* @param beanName must not be {@code null}
|
* @param beanName must not be {@code null}
|
||||||
* @throws IllegalArgumentException if beanName is null (as of Spring 3.1.1)
|
|
||||||
* @see ConfigurationClass#ConfigurationClass(Class, ConfigurationClass)
|
* @see ConfigurationClass#ConfigurationClass(Class, ConfigurationClass)
|
||||||
*/
|
*/
|
||||||
public ConfigurationClass(MetadataReader metadataReader, String beanName) {
|
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.metadata = metadataReader.getAnnotationMetadata();
|
||||||
this.resource = metadataReader.getResource();
|
this.resource = metadataReader.getResource();
|
||||||
this.beanName = beanName;
|
this.beanName = beanName;
|
||||||
@@ -96,7 +95,6 @@ final class ConfigurationClass {
|
|||||||
* Create a new {@link ConfigurationClass} with the given name.
|
* Create a new {@link ConfigurationClass} with the given name.
|
||||||
* @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 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)
|
* @see ConfigurationClass#ConfigurationClass(Class, ConfigurationClass)
|
||||||
*/
|
*/
|
||||||
public ConfigurationClass(Class<?> clazz, String beanName) {
|
public ConfigurationClass(Class<?> clazz, String beanName) {
|
||||||
@@ -120,6 +118,19 @@ final class ConfigurationClass {
|
|||||||
this.importedBy.add(importedBy);
|
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() {
|
public AnnotationMetadata getMetadata() {
|
||||||
return this.metadata;
|
return this.metadata;
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import org.springframework.beans.factory.BeanClassLoaderAware;
|
|||||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||||
import org.springframework.beans.factory.BeanFactory;
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
import org.springframework.beans.factory.BeanFactoryAware;
|
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.BeanDefinition;
|
||||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||||
@@ -158,7 +159,10 @@ class ConfigurationClassParser {
|
|||||||
for (BeanDefinitionHolder holder : configCandidates) {
|
for (BeanDefinitionHolder holder : configCandidates) {
|
||||||
BeanDefinition bd = holder.getBeanDefinition();
|
BeanDefinition bd = holder.getBeanDefinition();
|
||||||
try {
|
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());
|
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -169,32 +173,26 @@ class ConfigurationClassParser {
|
|||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
catch (Exception 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();
|
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 {
|
protected final void parse(String className, String beanName) throws IOException {
|
||||||
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
|
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
|
||||||
processConfigurationClass(new ConfigurationClass(reader, beanName));
|
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 {
|
protected final void parse(Class<?> clazz, String beanName) throws IOException {
|
||||||
processConfigurationClass(new ConfigurationClass(clazz, beanName));
|
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 {
|
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
|
||||||
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
|
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.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
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.config.BeanDefinition;
|
||||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||||
import org.springframework.core.Conventions;
|
import org.springframework.core.Conventions;
|
||||||
@@ -70,41 +71,47 @@ abstract class ConfigurationClassUtils {
|
|||||||
* @return whether the candidate qualifies as (any kind of) configuration class
|
* @return whether the candidate qualifies as (any kind of) configuration class
|
||||||
*/
|
*/
|
||||||
public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
|
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...
|
AnnotationMetadata metadata;
|
||||||
// since we possibly can't even load the class file for this Class.
|
if (beanDef instanceof AnnotatedBeanDefinition &&
|
||||||
if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
|
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();
|
Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
|
||||||
metadata = new StandardAnnotationMetadata(beanClass, true);
|
metadata = new StandardAnnotationMetadata(beanClass, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
String className = beanDef.getBeanClassName();
|
try {
|
||||||
if (className != null) {
|
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
|
||||||
try {
|
metadata = metadataReader.getAnnotationMetadata();
|
||||||
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
|
}
|
||||||
metadata = metadataReader.getAnnotationMetadata();
|
catch (IOException ex) {
|
||||||
}
|
if (logger.isDebugEnabled()) {
|
||||||
catch (IOException ex) {
|
logger.debug("Could not find class file for introspecting configuration annotations: " + className, ex);
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("Could not find class file for introspecting factory methods: " + className, ex);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (metadata != null) {
|
if (isFullConfigurationCandidate(metadata)) {
|
||||||
if (isFullConfigurationCandidate(metadata)) {
|
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
|
||||||
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
else if (isLiteConfigurationCandidate(metadata)) {
|
||||||
else if (isLiteConfigurationCandidate(metadata)) {
|
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
|
||||||
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user