Skip to content

Commit

Permalink
Final merged bean definition clearing in freezeConfiguration
Browse files Browse the repository at this point in the history
Instead of individual last-minute clearing in markBeanAsCreated, the factory clears all merged bean definitions in freezeConfiguration, retaining the changes of merged bean definition post-processing after that point (in particular in refreshForAotProcessing).

Closes gh-28948
  • Loading branch information
jhoeller committed Aug 19, 2022
1 parent 7c91776 commit 427e5f5
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2022 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.
Expand Down Expand Up @@ -137,14 +137,18 @@ boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
/**
* Freeze all bean definitions, signalling that the registered bean definitions
* will not be modified or post-processed any further.
* <p>This allows the factory to aggressively cache bean definition metadata.
* <p>This allows the factory to aggressively cache bean definition metadata
* going forward, after clearing the initial temporary metadata cache.
* @see #clearMetadataCache()
* @see #isConfigurationFrozen()
*/
void freezeConfiguration();

/**
* Return whether this factory's bean definitions are frozen,
* i.e. are not supposed to be modified or post-processed any further.
* @return {@code true} if the factory's configuration is considered frozen
* @see #freezeConfiguration()
*/
boolean isConfigurationFrozen();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
mbd.markAsPostProcessed();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1700,12 +1700,12 @@ ResolvableType getTypeForFactoryBeanFromAttributes(AttributeAccessor attributes)
protected void markBeanAsCreated(String beanName) {
if (!this.alreadyCreated.contains(beanName)) {
synchronized (this.mergedBeanDefinitions) {
if (!this.alreadyCreated.contains(beanName)) {
if (!isBeanEligibleForMetadataCaching(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);
this.alreadyCreated.add(beanName);
}
this.alreadyCreated.add(beanName);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,7 @@ public void clearMetadataCache() {

@Override
public void freezeConfiguration() {
clearMetadataCache();
this.configurationFrozen = true;
this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,17 @@ public void setInstanceSupplier(@Nullable Supplier<?> instanceSupplier) {
}
}

/**
* Mark this bean definition as post-processed,
* i.e. processed by {@link MergedBeanDefinitionPostProcessor}.
* @since 6.0
*/
public void markAsPostProcessed() {
synchronized (this.postProcessingLock) {
this.postProcessed = true;
}
}

/**
* Register an externally managed configuration method or field.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,29 @@ void getTypeWorksAfterParentChildMerging() {
assertThat(factory.getType("child")).isEqualTo(DerivedTestBean.class);
}

@Test
void mergedBeanDefinitionChangesRetainedAfterFreezeConfiguration() {
RootBeanDefinition parentDefinition = new RootBeanDefinition(Object.class);
ChildBeanDefinition childDefinition = new ChildBeanDefinition("parent");

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
factory.registerBeanDefinition("parent", parentDefinition);
factory.registerBeanDefinition("child", childDefinition);

assertThat(factory.getType("parent")).isEqualTo(Object.class);
assertThat(factory.getType("child")).isEqualTo(Object.class);
((RootBeanDefinition) factory.getBeanDefinition("parent")).setBeanClass(TestBean.class);

factory.freezeConfiguration();

assertThat(factory.getType("parent")).isEqualTo(TestBean.class);
assertThat(factory.getType("child")).isEqualTo(TestBean.class);
((RootBeanDefinition) factory.getMergedBeanDefinition("child")).setBeanClass(DerivedTestBean.class);

assertThat(factory.getBean("parent")).isInstanceOf(TestBean.class);
assertThat(factory.getBean("child")).isInstanceOf(DerivedTestBean.class);
}

@Test
void nameAlreadyBound() {
Properties p = new Properties();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@ private boolean isInfrastructureBean(@Nullable String beanName) {
}
}


private static final class MergedBeanDefinitionPostProcessorInvoker {

private final DefaultListableBeanFactory beanFactory;
Expand All @@ -438,12 +439,14 @@ private void invokeMergedBeanDefinitionPostProcessors() {
RootBeanDefinition bd = (RootBeanDefinition) this.beanFactory.getMergedBeanDefinition(beanName);
Class<?> beanType = resolveBeanType(bd);
postProcessRootBeanDefinition(postProcessors, beanName, beanType, bd);
bd.markAsPostProcessed();
}
registerBeanPostProcessors(this.beanFactory, postProcessors);
}

private void postProcessRootBeanDefinition(List<MergedBeanDefinitionPostProcessor> postProcessors,
String beanName, Class<?> beanType, RootBeanDefinition bd) {

BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this.beanFactory, beanName, bd);
postProcessors.forEach(postProcessor -> postProcessor.postProcessMergedBeanDefinition(bd, beanType, beanName));
for (PropertyValue propertyValue : bd.getPropertyValues().getPropertyValueList()) {
Expand All @@ -466,6 +469,7 @@ private void postProcessRootBeanDefinition(List<MergedBeanDefinitionPostProcesso

private void resolveInnerBeanDefinition(BeanDefinitionValueResolver valueResolver, BeanDefinition innerBeanDefinition,
BiConsumer<String, RootBeanDefinition> resolver) {

valueResolver.resolveInnerBean(null, innerBeanDefinition, (name, rbd) -> {
resolver.accept(name, rbd);
return Void.class;
Expand Down

0 comments on commit 427e5f5

Please sign in to comment.