Browse Source

Merged bean definitions are now cached early and selectively evicted after post-processing and before actual bean creation

Issue: SPR-12236
pull/838/head
Juergen Hoeller 9 years ago
parent
commit
09eb492079
  1. 14
      spring-beans/src/main/java/org/springframework/beans/factory/config/ConfigurableListableBeanFactory.java
  2. 24
      spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java
  3. 6
      spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
  4. 4
      spring-context/src/main/java/org/springframework/context/support/PostProcessorRegistrationDelegate.java

14
spring-beans/src/main/java/org/springframework/beans/factory/config/ConfigurableListableBeanFactory.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@ -121,6 +121,18 @@ public interface ConfigurableListableBeanFactory @@ -121,6 +121,18 @@ public interface ConfigurableListableBeanFactory
*/
Iterator<String> getBeanNamesIterator();
/**
* Clear the merged bean definition cache, removing entries for beans
* which are not considered eligible for full metadata caching yet.
* <p>Typically triggered after changes to the original bean definitions,
* e.g. after applying a {@link BeanFactoryPostProcessor}. Note that metadata
* for beans which have already been created at this point will be kept around.
* @since 4.2
* @see #getBeanDefinition
* @see #getMergedBeanDefinition
*/
void clearMetadataCache();
/**
* Freeze all bean definitions, signalling that the registered bean definitions
* will not be modified or post-processed any further.

24
spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java

@ -27,6 +27,7 @@ import java.util.Arrays; @@ -27,6 +27,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
@ -1262,7 +1263,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp @@ -1262,7 +1263,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
// Only cache the merged bean definition if we're already about to create an
// instance of the bean, or at least have already created an instance before.
if (containingBd == null && isCacheBeanMetadata() && isBeanEligibleForMetadataCaching(beanName)) {
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
@ -1296,6 +1297,23 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp @@ -1296,6 +1297,23 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
this.mergedBeanDefinitions.remove(beanName);
}
/**
* Clear the merged bean definition cache, removing entries for beans
* which are not considered eligible for full metadata caching yet.
* <p>Typically triggered after changes to the original bean definitions,
* e.g. after applying a {@code BeanFactoryPostProcessor}. Note that metadata
* for beans which have already been created at this point will be kept around.
* @since 4.2
*/
public void clearMetadataCache() {
Iterator<String> mergedBeans = this.mergedBeanDefinitions.keySet().iterator();
while (mergedBeans.hasNext()) {
if (!isBeanEligibleForMetadataCaching(mergedBeans.next())) {
mergedBeans.remove();
}
}
}
/**
* Resolve the bean class for the specified bean definition,
* resolving a bean class name into a Class reference (if necessary)
@ -1475,6 +1493,10 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp @@ -1475,6 +1493,10 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
protected void markBeanAsCreated(String beanName) {
if (!this.alreadyCreated.contains(beanName)) {
this.alreadyCreated.add(beanName);
// Let the bean definition get re-merged now that we're actually creating
// the bean... just in case some of its metadata changed in the meantime.
clearMergedBeanDefinition(beanName);
}
}

6
spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java

@ -708,6 +708,12 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto @@ -708,6 +708,12 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
return iterator;
}
@Override
public void clearMetadataCache() {
super.clearMetadataCache();
clearByTypeCache();
}
@Override
public void freezeConfiguration() {
this.configurationFrozen = true;

4
spring-context/src/main/java/org/springframework/context/support/PostProcessorRegistrationDelegate.java

@ -179,6 +179,10 @@ class PostProcessorRegistrationDelegate { @@ -179,6 +179,10 @@ class PostProcessorRegistrationDelegate {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
public static void registerBeanPostProcessors(

Loading…
Cancel
Save