diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/ConfigurableListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/ConfigurableListableBeanFactory.java
index 2dc8ec6fae..0c5ee75fed 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/config/ConfigurableListableBeanFactory.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/ConfigurableListableBeanFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -16,6 +16,8 @@
package org.springframework.beans.factory.config;
+import java.util.Iterator;
+
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
@@ -105,6 +107,20 @@ public interface ConfigurableListableBeanFactory
*/
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
+ /**
+ * Return a unified view over all bean names managed by this factory.
+ *
Includes bean definition names as well as names of manually registered
+ * singleton instances, with bean definition names consistently coming first,
+ * analogous to how type/annotation specific retrieval of bean names works.
+ * @return the composite iterator for the bean names view
+ * @since 4.1.2
+ * @see #containsBeanDefinition
+ * @see #registerSingleton
+ * @see #getBeanNamesForType
+ * @see #getBeanNamesForAnnotation
+ */
+ Iterator getBeanNamesIterator();
+
/**
* Freeze all bean definitions, signalling that the registered bean definitions
* will not be modified or post-processed any further.
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
index 843ae4b80a..93e646070f 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
@@ -34,7 +34,9 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.IdentityHashMap;
+import java.util.Iterator;
import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -68,6 +70,7 @@ import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.lang.UsesJava8;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
+import org.springframework.util.CompositeIterator;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -156,14 +159,17 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
/** Map of bean definition objects, keyed by bean name */
private final Map beanDefinitionMap = new ConcurrentHashMap(64);
- /** Map of singleton and non-singleton bean names keyed by dependency type */
+ /** Map of singleton and non-singleton bean names, keyed by dependency type */
private final Map, String[]> allBeanNamesByType = new ConcurrentHashMap, String[]>(64);
- /** Map of singleton-only bean names keyed by dependency type */
+ /** Map of singleton-only bean names, keyed by dependency type */
private final Map, String[]> singletonBeanNamesByType = new ConcurrentHashMap, String[]>(64);
/** List of bean definition names, in registration order */
- private final List beanDefinitionNames = new ArrayList();
+ private final List beanDefinitionNames = new ArrayList(64);
+
+ /** List of names of manually registered singletons, in registration order */
+ private final Set manualSingletonNames = new LinkedHashSet(16);
/** Whether bean definition metadata may be cached for all beans */
private boolean configurationFrozen = false;
@@ -202,6 +208,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
this.serializationId = serializationId;
}
+ /**
+ * Return an id for serialization purposes, if specified, allowing this BeanFactory
+ * to be deserialized from this id back into the BeanFactory object, if needed.
+ * @since 4.1.2
+ */
+ public String getSerializationId() {
+ return this.serializationId;
+ }
+
/**
* Set whether it should be allowed to override bean definitions by registering
* a different definition with the same name, automatically replacing the former.
@@ -213,6 +228,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
this.allowBeanDefinitionOverriding = allowBeanDefinitionOverriding;
}
+ /**
+ * Return whether it should be allowed to override bean definitions by registering
+ * a different definition with the same name, automatically replacing the former.
+ * @since 4.1.2
+ */
+ public boolean isAllowBeanDefinitionOverriding() {
+ return this.allowBeanDefinitionOverriding;
+ }
+
/**
* Set whether the factory is allowed to eagerly load bean classes
* even for bean definitions that are marked as "lazy-init".
@@ -227,6 +251,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
this.allowEagerClassLoading = allowEagerClassLoading;
}
+ /**
+ * Return whether the factory is allowed to eagerly load bean classes
+ * even for bean definitions that are marked as "lazy-init".
+ * @since 4.1.2
+ */
+ public boolean isAllowEagerClassLoading() {
+ return this.allowEagerClassLoading;
+ }
+
/**
* Set a {@link java.util.Comparator} for dependency Lists and arrays.
* @see org.springframework.core.OrderComparator
@@ -352,13 +385,11 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@Override
public String[] getBeanDefinitionNames() {
- synchronized (this.beanDefinitionMap) {
- if (this.frozenBeanDefinitionNames != null) {
- return this.frozenBeanDefinitionNames;
- }
- else {
- return StringUtils.toStringArray(this.beanDefinitionNames);
- }
+ if (this.frozenBeanDefinitionNames != null) {
+ return this.frozenBeanDefinitionNames;
+ }
+ else {
+ return StringUtils.toStringArray(this.beanDefinitionNames);
}
}
@@ -389,8 +420,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
List result = new ArrayList();
// Check all bean definitions.
- String[] beanDefinitionNames = getBeanDefinitionNames();
- for (String beanName : beanDefinitionNames) {
+ for (String beanName : this.beanDefinitionNames) {
// Only consider bean as eligible if the bean name
// is not defined as alias for some other bean.
if (!isAlias(beanName)) {
@@ -398,7 +428,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// Only check bean definition if it is complete.
if (!mbd.isAbstract() && (allowEagerInit ||
- ((mbd.hasBeanClass() || !mbd.isLazyInit() || this.allowEagerClassLoading)) &&
+ ((mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading())) &&
!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
// In case of FactoryBean, match object created by FactoryBean.
boolean isFactoryBean = isFactoryBean(beanName, mbd);
@@ -437,9 +467,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
}
- // Check singletons too, to catch manually registered singletons.
- String[] singletonNames = getSingletonNames();
- for (String beanName : singletonNames) {
+ // Check manually registered singletons too.
+ for (String beanName : this.manualSingletonNames) {
// Only check if manually registered.
if (!containsBeanDefinition(beanName)) {
// In case of FactoryBean, match object created by FactoryBean.
@@ -512,13 +541,13 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@Override
public String[] getBeanNamesForAnnotation(Class extends Annotation> annotationType) {
List results = new ArrayList();
- for (String beanName : getBeanDefinitionNames()) {
+ for (String beanName : this.beanDefinitionNames) {
BeanDefinition beanDefinition = getBeanDefinition(beanName);
if (!beanDefinition.isAbstract() && findAnnotationOnBean(beanName, annotationType) != null) {
results.add(beanName);
}
}
- for (String beanName : getSingletonNames()) {
+ for (String beanName : this.manualSingletonNames) {
if (!results.contains(beanName) && findAnnotationOnBean(beanName, annotationType) != null) {
results.add(beanName);
}
@@ -529,13 +558,13 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
@Override
public Map getBeansWithAnnotation(Class extends Annotation> annotationType) {
Map results = new LinkedHashMap();
- for (String beanName : getBeanDefinitionNames()) {
+ for (String beanName : this.beanDefinitionNames) {
BeanDefinition beanDefinition = getBeanDefinition(beanName);
if (!beanDefinition.isAbstract() && findAnnotationOnBean(beanName, annotationType) != null) {
results.put(beanName, getBean(beanName));
}
}
- for (String beanName : getSingletonNames()) {
+ for (String beanName : this.manualSingletonNames) {
if (!results.containsKey(beanName) && findAnnotationOnBean(beanName, annotationType) != null) {
results.put(beanName, getBean(beanName));
}
@@ -662,12 +691,18 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
return bd;
}
+ @Override
+ public Iterator getBeanNamesIterator() {
+ CompositeIterator iterator = new CompositeIterator();
+ iterator.add(this.beanDefinitionNames.iterator());
+ iterator.add(this.manualSingletonNames.iterator());
+ return iterator;
+ }
+
@Override
public void freezeConfiguration() {
this.configurationFrozen = true;
- synchronized (this.beanDefinitionMap) {
- this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
- }
+ this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
}
@Override
@@ -691,12 +726,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
this.logger.debug("Pre-instantiating singletons in " + this);
}
- List beanNames;
- synchronized (this.beanDefinitionMap) {
- // Iterate over a copy to allow for init methods which in turn register new bean definitions.
- // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
- beanNames = new ArrayList(this.beanDefinitionNames);
- }
+ // Iterate over a copy to allow for init methods which in turn register new bean definitions.
+ // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
+ List beanNames = new ArrayList(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
@@ -772,35 +804,34 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
BeanDefinition oldBeanDefinition;
- synchronized (this.beanDefinitionMap) {
- oldBeanDefinition = this.beanDefinitionMap.get(beanName);
- if (oldBeanDefinition != null) {
- if (!this.allowBeanDefinitionOverriding) {
- throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
- "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
- "': There is already [" + oldBeanDefinition + "] bound.");
- }
- else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
- // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
- if (this.logger.isWarnEnabled()) {
- this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
- " with a framework-generated bean definition ': replacing [" +
- oldBeanDefinition + "] with [" + beanDefinition + "]");
- }
- }
- else {
- if (this.logger.isInfoEnabled()) {
- this.logger.info("Overriding bean definition for bean '" + beanName +
- "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
- }
+ oldBeanDefinition = this.beanDefinitionMap.get(beanName);
+ if (oldBeanDefinition != null) {
+ if (!this.allowBeanDefinitionOverriding) {
+ throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
+ "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
+ "': There is already [" + oldBeanDefinition + "] bound.");
+ }
+ else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
+ // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
+ if (this.logger.isWarnEnabled()) {
+ this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
+ " with a framework-generated bean definition ': replacing [" +
+ oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else {
- this.beanDefinitionNames.add(beanName);
- this.frozenBeanDefinitionNames = null;
+ if (this.logger.isInfoEnabled()) {
+ this.logger.info("Overriding bean definition for bean '" + beanName +
+ "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
+ }
}
- this.beanDefinitionMap.put(beanName, beanDefinition);
}
+ else {
+ this.beanDefinitionNames.add(beanName);
+ this.manualSingletonNames.remove(beanName);
+ this.frozenBeanDefinitionNames = null;
+ }
+ this.beanDefinitionMap.put(beanName, beanDefinition);
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
@@ -811,17 +842,15 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
Assert.hasText(beanName, "'beanName' must not be empty");
- synchronized (this.beanDefinitionMap) {
- BeanDefinition bd = this.beanDefinitionMap.remove(beanName);
- if (bd == null) {
- if (this.logger.isTraceEnabled()) {
- this.logger.trace("No bean named '" + beanName + "' found in " + this);
- }
- throw new NoSuchBeanDefinitionException(beanName);
+ BeanDefinition bd = this.beanDefinitionMap.remove(beanName);
+ if (bd == null) {
+ if (this.logger.isTraceEnabled()) {
+ this.logger.trace("No bean named '" + beanName + "' found in " + this);
}
- this.beanDefinitionNames.remove(beanName);
- this.frozenBeanDefinitionNames = null;
+ throw new NoSuchBeanDefinitionException(beanName);
}
+ this.beanDefinitionNames.remove(beanName);
+ this.frozenBeanDefinitionNames = null;
resetBeanDefinition(beanName);
}
@@ -856,18 +885,22 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
*/
@Override
protected boolean allowAliasOverriding() {
- return this.allowBeanDefinitionOverriding;
+ return isAllowBeanDefinitionOverriding();
}
@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
super.registerSingleton(beanName, singletonObject);
+ if (!this.beanDefinitionMap.containsKey(beanName)) {
+ this.manualSingletonNames.add(beanName);
+ }
clearByTypeCache();
}
@Override
public void destroySingleton(String beanName) {
super.destroySingleton(beanName);
+ this.manualSingletonNames.remove(beanName);
clearByTypeCache();
}
@@ -940,7 +973,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
Object result = converter.convertIfNecessary(matchingBeans.values(), type);
- if (this.dependencyComparator != null && result instanceof Object[]) {
+ if (getDependencyComparator() != null && result instanceof Object[]) {
Arrays.sort((Object[]) result, adaptDependencyComparator(matchingBeans));
}
return result;
@@ -967,7 +1000,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
Object result = converter.convertIfNecessary(matchingBeans.values(), type);
- if (this.dependencyComparator != null && result instanceof List) {
+ if (getDependencyComparator() != null && result instanceof List) {
Collections.sort((List>) result, adaptDependencyComparator(matchingBeans));
}
return result;
@@ -1030,12 +1063,13 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
private Comparator