Skip to content

Commit 09eb492

Browse files
committed
Merged bean definitions are now cached early and selectively evicted after post-processing and before actual bean creation
Issue: SPR-12236
1 parent 37f74e7 commit 09eb492

File tree

4 files changed

+46
-2
lines changed

4 files changed

+46
-2
lines changed

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -121,6 +121,18 @@ boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
121121
*/
122122
Iterator<String> getBeanNamesIterator();
123123

124+
/**
125+
* Clear the merged bean definition cache, removing entries for beans
126+
* which are not considered eligible for full metadata caching yet.
127+
* <p>Typically triggered after changes to the original bean definitions,
128+
* e.g. after applying a {@link BeanFactoryPostProcessor}. Note that metadata
129+
* for beans which have already been created at this point will be kept around.
130+
* @since 4.2
131+
* @see #getBeanDefinition
132+
* @see #getMergedBeanDefinition
133+
*/
134+
void clearMetadataCache();
135+
124136
/**
125137
* Freeze all bean definitions, signalling that the registered bean definitions
126138
* will not be modified or post-processed any further.

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

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.Collections;
2828
import java.util.HashMap;
2929
import java.util.HashSet;
30+
import java.util.Iterator;
3031
import java.util.LinkedHashMap;
3132
import java.util.LinkedHashSet;
3233
import java.util.LinkedList;
@@ -1262,7 +1263,7 @@ protected RootBeanDefinition getMergedBeanDefinition(
12621263

12631264
// Only cache the merged bean definition if we're already about to create an
12641265
// instance of the bean, or at least have already created an instance before.
1265-
if (containingBd == null && isCacheBeanMetadata() && isBeanEligibleForMetadataCaching(beanName)) {
1266+
if (containingBd == null && isCacheBeanMetadata()) {
12661267
this.mergedBeanDefinitions.put(beanName, mbd);
12671268
}
12681269
}
@@ -1296,6 +1297,23 @@ protected void clearMergedBeanDefinition(String beanName) {
12961297
this.mergedBeanDefinitions.remove(beanName);
12971298
}
12981299

1300+
/**
1301+
* Clear the merged bean definition cache, removing entries for beans
1302+
* which are not considered eligible for full metadata caching yet.
1303+
* <p>Typically triggered after changes to the original bean definitions,
1304+
* e.g. after applying a {@code BeanFactoryPostProcessor}. Note that metadata
1305+
* for beans which have already been created at this point will be kept around.
1306+
* @since 4.2
1307+
*/
1308+
public void clearMetadataCache() {
1309+
Iterator<String> mergedBeans = this.mergedBeanDefinitions.keySet().iterator();
1310+
while (mergedBeans.hasNext()) {
1311+
if (!isBeanEligibleForMetadataCaching(mergedBeans.next())) {
1312+
mergedBeans.remove();
1313+
}
1314+
}
1315+
}
1316+
12991317
/**
13001318
* Resolve the bean class for the specified bean definition,
13011319
* resolving a bean class name into a Class reference (if necessary)
@@ -1475,6 +1493,10 @@ protected Class<?> getTypeForFactoryBean(String beanName, RootBeanDefinition mbd
14751493
protected void markBeanAsCreated(String beanName) {
14761494
if (!this.alreadyCreated.contains(beanName)) {
14771495
this.alreadyCreated.add(beanName);
1496+
1497+
// Let the bean definition get re-merged now that we're actually creating
1498+
// the bean... just in case some of its metadata changed in the meantime.
1499+
clearMergedBeanDefinition(beanName);
14781500
}
14791501
}
14801502

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,12 @@ public Iterator<String> getBeanNamesIterator() {
708708
return iterator;
709709
}
710710

711+
@Override
712+
public void clearMetadataCache() {
713+
super.clearMetadataCache();
714+
clearByTypeCache();
715+
}
716+
711717
@Override
712718
public void freezeConfiguration() {
713719
this.configurationFrozen = true;

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
179179
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
180180
}
181181
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
182+
183+
// Clear cached merged bean definitions since the post-processors might have
184+
// modified the original metadata, e.g. replacing placeholders in values...
185+
beanFactory.clearMetadataCache();
182186
}
183187

184188
public static void registerBeanPostProcessors(

0 commit comments

Comments
 (0)