introduced BeanDefinitionRegistryPostProcessor extension to BeanFactoryPostProcessor; @Configuration classes support definition of BeanFactoryPostProcessor beans as well (SPR-6455, SPR-6611)
This commit is contained in:
@@ -27,6 +27,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.annotation.Autowire;
|
||||
import org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor;
|
||||
@@ -48,7 +49,6 @@ import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.core.type.MethodMetadata;
|
||||
import org.springframework.core.type.StandardAnnotationMetadata;
|
||||
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -68,11 +68,11 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
class ConfigurationClassBeanDefinitionReader {
|
||||
|
||||
static final String CONFIGURATION_CLASS_FULL = "full";
|
||||
private static final String CONFIGURATION_CLASS_FULL = "full";
|
||||
|
||||
static final String CONFIGURATION_CLASS_LITE = "lite";
|
||||
private static final String CONFIGURATION_CLASS_LITE = "lite";
|
||||
|
||||
static final String CONFIGURATION_CLASS_ATTRIBUTE =
|
||||
private static final String CONFIGURATION_CLASS_ATTRIBUTE =
|
||||
Conventions.getQualifiedAttributeName(ConfigurationClassPostProcessor.class, "configurationClass");
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ConfigurationClassBeanDefinitionReader.class);
|
||||
@@ -86,7 +86,6 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
private final MetadataReaderFactory metadataReaderFactory;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@link ConfigurationClassBeanDefinitionReader} instance that will be used
|
||||
* to populate the given {@link BeanDefinitionRegistry}.
|
||||
@@ -95,6 +94,7 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
*/
|
||||
public ConfigurationClassBeanDefinitionReader(BeanDefinitionRegistry registry, SourceExtractor sourceExtractor,
|
||||
ProblemReporter problemReporter, MetadataReaderFactory metadataReaderFactory) {
|
||||
|
||||
this.registry = registry;
|
||||
this.sourceExtractor = sourceExtractor;
|
||||
this.problemReporter = problemReporter;
|
||||
@@ -145,13 +145,15 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Registered bean definition for imported @Configuration class %s", configBeanName));
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
try {
|
||||
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
|
||||
AnnotationMetadata metadata = reader.getAnnotationMetadata();
|
||||
this.problemReporter.error(
|
||||
new InvalidConfigurationImportProblem(className, reader.getResource(), metadata));
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException("Could not create MetadataReader for class " + className);
|
||||
}
|
||||
}
|
||||
@@ -181,7 +183,7 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
this.registry.registerAlias(beanName, alias);
|
||||
}
|
||||
|
||||
// has this already been overriden (i.e.: via XML)?
|
||||
// has this already been overridden (e.g. via XML)?
|
||||
if (this.registry.containsBeanDefinition(beanName)) {
|
||||
BeanDefinition existingBeanDef = registry.getBeanDefinition(beanName);
|
||||
// is the existing bean definition one that was created from a configuration class?
|
||||
@@ -277,6 +279,7 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check whether the given bean definition is a candidate for a configuration class,
|
||||
* and mark it accordingly.
|
||||
@@ -284,7 +287,7 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
* @param metadataReaderFactory the current factory in use by the caller
|
||||
* @return whether the candidate qualifies as (any kind of) configuration class
|
||||
*/
|
||||
static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
|
||||
public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
|
||||
AnnotationMetadata metadata = null;
|
||||
|
||||
// Check already loaded Class if present...
|
||||
@@ -322,6 +325,14 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given bean definition indicates a full @Configuration class.
|
||||
*/
|
||||
public static boolean isFullConfigurationClass(BeanDefinition beanDef) {
|
||||
return CONFIGURATION_CLASS_FULL.equals(beanDef.getAttribute(CONFIGURATION_CLASS_ATTRIBUTE));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@link RootBeanDefinition} marker subclass used to signify that a bean definition
|
||||
* created from a configuration class as opposed to any other configuration source.
|
||||
@@ -329,7 +340,7 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
* definition was created externally.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
private class ConfigurationClassBeanDefinition extends RootBeanDefinition implements AnnotatedBeanDefinition {
|
||||
private static class ConfigurationClassBeanDefinition extends RootBeanDefinition implements AnnotatedBeanDefinition {
|
||||
|
||||
private AnnotationMetadata annotationMetadata;
|
||||
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import static org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.CONFIGURATION_CLASS_ATTRIBUTE;
|
||||
import static org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.CONFIGURATION_CLASS_FULL;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
@@ -40,6 +37,7 @@ import org.springframework.beans.factory.parsing.ProblemReporter;
|
||||
import org.springframework.beans.factory.parsing.SourceExtractor;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
@@ -63,7 +61,7 @@ import org.springframework.util.ClassUtils;
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public class ConfigurationClassPostProcessor implements BeanFactoryPostProcessor, BeanClassLoaderAware {
|
||||
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, BeanClassLoaderAware {
|
||||
|
||||
/** Whether the CGLIB2 library is present on the classpath */
|
||||
private static final boolean cglibAvailable = ClassUtils.isPresent(
|
||||
@@ -124,16 +122,18 @@ public class ConfigurationClassPostProcessor implements BeanFactoryPostProcessor
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Derive further bean definitions from the configuration classes in the registry.
|
||||
*/
|
||||
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
|
||||
processConfigBeanDefinitions(registry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the Configuration classes for servicing bean requests at runtime
|
||||
* by replacing them with CGLIB-enhanced subclasses.
|
||||
*/
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
|
||||
if (!(beanFactory instanceof BeanDefinitionRegistry)) {
|
||||
throw new IllegalStateException(
|
||||
"ConfigurationClassPostProcessor expects a BeanFactory that implements BeanDefinitionRegistry");
|
||||
}
|
||||
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
|
||||
enhanceConfigurationClasses(beanFactory);
|
||||
}
|
||||
|
||||
@@ -174,8 +174,8 @@ public class ConfigurationClassPostProcessor implements BeanFactoryPostProcessor
|
||||
parser.validate();
|
||||
|
||||
// Read the model and create bean definitions based on its content
|
||||
ConfigurationClassBeanDefinitionReader reader =
|
||||
new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.problemReporter, this.metadataReaderFactory);
|
||||
ConfigurationClassBeanDefinitionReader reader = new ConfigurationClassBeanDefinitionReader(
|
||||
registry, this.sourceExtractor, this.problemReporter, this.metadataReaderFactory);
|
||||
reader.loadBeanDefinitions(parser.getConfigurationClasses());
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ public class ConfigurationClassPostProcessor implements BeanFactoryPostProcessor
|
||||
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<String, AbstractBeanDefinition>();
|
||||
for (String beanName : beanFactory.getBeanDefinitionNames()) {
|
||||
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
|
||||
if (CONFIGURATION_CLASS_FULL.equals(beanDef.getAttribute(CONFIGURATION_CLASS_ATTRIBUTE))) {
|
||||
if (ConfigurationClassBeanDefinitionReader.isFullConfigurationClass(beanDef)) {
|
||||
if (!(beanDef instanceof AbstractBeanDefinition)) {
|
||||
throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
|
||||
beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 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.
|
||||
@@ -39,6 +39,8 @@ import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
|
||||
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
|
||||
import org.springframework.beans.support.ResourceEditorRegistrar;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -569,6 +571,21 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
* <p>Must be called before singleton instantiation.
|
||||
*/
|
||||
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
|
||||
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
|
||||
if (beanFactory instanceof BeanDefinitionRegistry) {
|
||||
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
|
||||
for (BeanFactoryPostProcessor postProcessor : getBeanFactoryPostProcessors()) {
|
||||
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
|
||||
((BeanDefinitionRegistryPostProcessor) postProcessor).postProcessBeanDefinitionRegistry(registry);
|
||||
}
|
||||
}
|
||||
Collection<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
|
||||
beanFactory.getBeansOfType(BeanDefinitionRegistryPostProcessor.class, true, false).values();
|
||||
for (BeanDefinitionRegistryPostProcessor postProcessor : registryPostProcessors) {
|
||||
postProcessor.postProcessBeanDefinitionRegistry(registry);
|
||||
}
|
||||
}
|
||||
|
||||
// Invoke factory processors registered with the context instance.
|
||||
invokeBeanFactoryPostProcessors(getBeanFactoryPostProcessors(), beanFactory);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user