|
1 | 1 | /*
|
2 |
| - * Copyright 2002-2024 the original author or authors. |
| 2 | + * Copyright 2002-2025 the original author or authors. |
3 | 3 | *
|
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
@@ -137,6 +137,9 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
137 | 137 | @Nullable
|
138 | 138 | private ConversionService conversionService;
|
139 | 139 |
|
| 140 | + /** Default PropertyEditorRegistrars to apply to the beans of this factory. */ |
| 141 | + private final Set<PropertyEditorRegistrar> defaultEditorRegistrars = new LinkedHashSet<>(4); |
| 142 | + |
140 | 143 | /** Custom PropertyEditorRegistrars to apply to the beans of this factory. */
|
141 | 144 | private final Set<PropertyEditorRegistrar> propertyEditorRegistrars = new LinkedHashSet<>(4);
|
142 | 145 |
|
@@ -883,7 +886,12 @@ public ConversionService getConversionService() {
|
883 | 886 | @Override
|
884 | 887 | public void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar) {
|
885 | 888 | Assert.notNull(registrar, "PropertyEditorRegistrar must not be null");
|
886 |
| - this.propertyEditorRegistrars.add(registrar); |
| 889 | + if (registrar.overridesDefaultEditors()) { |
| 890 | + this.defaultEditorRegistrars.add(registrar); |
| 891 | + } |
| 892 | + else { |
| 893 | + this.propertyEditorRegistrars.add(registrar); |
| 894 | + } |
887 | 895 | }
|
888 | 896 |
|
889 | 897 | /**
|
@@ -1114,6 +1122,7 @@ public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
|
1114 | 1122 | setBeanExpressionResolver(otherFactory.getBeanExpressionResolver());
|
1115 | 1123 | setConversionService(otherFactory.getConversionService());
|
1116 | 1124 | if (otherFactory instanceof AbstractBeanFactory otherAbstractFactory) {
|
| 1125 | + this.defaultEditorRegistrars.addAll(otherAbstractFactory.defaultEditorRegistrars); |
1117 | 1126 | this.propertyEditorRegistrars.addAll(otherAbstractFactory.propertyEditorRegistrars);
|
1118 | 1127 | this.customEditors.putAll(otherAbstractFactory.customEditors);
|
1119 | 1128 | this.typeConverter = otherAbstractFactory.typeConverter;
|
@@ -1313,36 +1322,48 @@ protected void initBeanWrapper(BeanWrapper bw) {
|
1313 | 1322 | protected void registerCustomEditors(PropertyEditorRegistry registry) {
|
1314 | 1323 | if (registry instanceof PropertyEditorRegistrySupport registrySupport) {
|
1315 | 1324 | registrySupport.useConfigValueEditors();
|
| 1325 | + if (!this.defaultEditorRegistrars.isEmpty()) { |
| 1326 | + // Optimization: lazy overriding of default editors only when needed |
| 1327 | + registrySupport.setDefaultEditorRegistrar(new BeanFactoryDefaultEditorRegistrar()); |
| 1328 | + } |
| 1329 | + } |
| 1330 | + else if (!this.defaultEditorRegistrars.isEmpty()) { |
| 1331 | + // Fallback: proactive overriding of default editors |
| 1332 | + applyEditorRegistrars(registry, this.defaultEditorRegistrars); |
1316 | 1333 | }
|
| 1334 | + |
1317 | 1335 | if (!this.propertyEditorRegistrars.isEmpty()) {
|
1318 |
| - for (PropertyEditorRegistrar registrar : this.propertyEditorRegistrars) { |
1319 |
| - try { |
1320 |
| - registrar.registerCustomEditors(registry); |
1321 |
| - } |
1322 |
| - catch (BeanCreationException ex) { |
1323 |
| - Throwable rootCause = ex.getMostSpecificCause(); |
1324 |
| - if (rootCause instanceof BeanCurrentlyInCreationException bce) { |
1325 |
| - String bceBeanName = bce.getBeanName(); |
1326 |
| - if (bceBeanName != null && isCurrentlyInCreation(bceBeanName)) { |
1327 |
| - if (logger.isDebugEnabled()) { |
1328 |
| - logger.debug("PropertyEditorRegistrar [" + registrar.getClass().getName() + |
1329 |
| - "] failed because it tried to obtain currently created bean '" + |
1330 |
| - ex.getBeanName() + "': " + ex.getMessage()); |
1331 |
| - } |
1332 |
| - onSuppressedException(ex); |
1333 |
| - continue; |
1334 |
| - } |
1335 |
| - } |
1336 |
| - throw ex; |
1337 |
| - } |
1338 |
| - } |
| 1336 | + applyEditorRegistrars(registry, this.propertyEditorRegistrars); |
1339 | 1337 | }
|
1340 | 1338 | if (!this.customEditors.isEmpty()) {
|
1341 | 1339 | this.customEditors.forEach((requiredType, editorClass) ->
|
1342 | 1340 | registry.registerCustomEditor(requiredType, BeanUtils.instantiateClass(editorClass)));
|
1343 | 1341 | }
|
1344 | 1342 | }
|
1345 | 1343 |
|
| 1344 | + private void applyEditorRegistrars(PropertyEditorRegistry registry, Set<PropertyEditorRegistrar> registrars) { |
| 1345 | + for (PropertyEditorRegistrar registrar : registrars) { |
| 1346 | + try { |
| 1347 | + registrar.registerCustomEditors(registry); |
| 1348 | + } |
| 1349 | + catch (BeanCreationException ex) { |
| 1350 | + Throwable rootCause = ex.getMostSpecificCause(); |
| 1351 | + if (rootCause instanceof BeanCurrentlyInCreationException bce) { |
| 1352 | + String bceBeanName = bce.getBeanName(); |
| 1353 | + if (bceBeanName != null && isCurrentlyInCreation(bceBeanName)) { |
| 1354 | + if (logger.isDebugEnabled()) { |
| 1355 | + logger.debug("PropertyEditorRegistrar [" + registrar.getClass().getName() + |
| 1356 | + "] failed because it tried to obtain currently created bean '" + |
| 1357 | + ex.getBeanName() + "': " + ex.getMessage()); |
| 1358 | + } |
| 1359 | + onSuppressedException(ex); |
| 1360 | + return; |
| 1361 | + } |
| 1362 | + } |
| 1363 | + throw ex; |
| 1364 | + } |
| 1365 | + } |
| 1366 | + } |
1346 | 1367 |
|
1347 | 1368 | /**
|
1348 | 1369 | * Return a merged RootBeanDefinition, traversing the parent bean definition
|
@@ -2095,4 +2116,20 @@ static class BeanPostProcessorCache {
|
2095 | 2116 | final List<MergedBeanDefinitionPostProcessor> mergedDefinition = new ArrayList<>();
|
2096 | 2117 | }
|
2097 | 2118 |
|
| 2119 | + |
| 2120 | + /** |
| 2121 | + * {@link PropertyEditorRegistrar} that delegates to the bean factory's |
| 2122 | + * default registrars, adding exception handling for circular reference |
| 2123 | + * scenarios where an editor tries to refer back to the currently created bean. |
| 2124 | + * |
| 2125 | + * @since 6.2.3 |
| 2126 | + */ |
| 2127 | + class BeanFactoryDefaultEditorRegistrar implements PropertyEditorRegistrar { |
| 2128 | + |
| 2129 | + @Override |
| 2130 | + public void registerCustomEditors(PropertyEditorRegistry registry) { |
| 2131 | + applyEditorRegistrars(registry, defaultEditorRegistrars); |
| 2132 | + } |
| 2133 | + } |
| 2134 | + |
2098 | 2135 | }
|
0 commit comments