📄 abstractbeanfactory.java
字号:
/*
* Copyright 2002-2007 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.support;
import java.beans.PropertyEditor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.PropertyEditorRegistrySupport;
import org.springframework.beans.SimpleTypeConverter;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanCurrentlyInCreationException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.BeanIsAbstractException;
import org.springframework.beans.factory.BeanIsNotAFactoryException;
import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
import org.springframework.beans.factory.CannotLoadBeanClassException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.FactoryBeanNotInitializedException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.SmartFactoryBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.config.Scope;
import org.springframework.core.CollectionFactory;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* Abstract base class for {@link org.springframework.beans.factory.BeanFactory}
* implementations, providing the full capabilities of the
* {@link org.springframework.beans.factory.config.ConfigurableBeanFactory} SPI.
* Does <i>not</i> assume a listable bean factory: can therefore also be used
* as base class for bean factory implementations which obtain bean definitions
* from some backend resource (where bean definition access is an expensive operation).
*
* <p>This class provides a singleton cache (through its base class
* {@link org.springframework.beans.factory.support.DefaultSingletonBeanRegistry},
* singleton/prototype determination, {@link org.springframework.beans.factory.FactoryBean}
* handling, aliases, bean definition merging for child bean definitions,
* and bean destruction ({@link org.springframework.beans.factory.DisposableBean}
* interface, custom destroy methods). Furthermore, it can manage a bean factory
* hierarchy (delegating to the parent in case of an unknown bean), through implementing
* the {@link org.springframework.beans.factory.HierarchicalBeanFactory} interface.
*
* <p>The main template methods to be implemented by subclasses are
* {@link #getBeanDefinition} and {@link #createBean}, retrieving a bean definition
* for a given bean name and creating a bean instance for a given bean definition,
* respectively. Default implementations of those operations can be found in
* {@link DefaultListableBeanFactory} and {@link AbstractAutowireCapableBeanFactory}.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since 15 April 2001
* @see #getBeanDefinition
* @see #createBean
* @see AbstractAutowireCapableBeanFactory#createBean
* @see DefaultListableBeanFactory#getBeanDefinition
*/
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements ConfigurableBeanFactory {
/** Parent bean factory, for bean inheritance support */
private BeanFactory parentBeanFactory;
/** ClassLoader to resolve bean class names with, if necessary */
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
/** Whether to cache bean metadata or rather reobtain it for every access */
private boolean cacheBeanMetadata = true;
/** Custom PropertyEditors to apply to the beans of this factory */
private final Map customEditors = new HashMap();
/** Custom PropertyEditorRegistrars to apply to the beans of this factory */
private final Set propertyEditorRegistrars = CollectionFactory.createLinkedSetIfPossible(16);
/** BeanPostProcessors to apply in createBean */
private final List beanPostProcessors = new ArrayList();
/** Indicates whether any InstantiationAwareBeanPostProcessors have been registered */
private boolean hasInstantiationAwareBeanPostProcessors;
/** Indicates whether any DestructionAwareBeanPostProcessors have been registered */
private boolean hasDestructionAwareBeanPostProcessors;
/** Map from scope identifier String to corresponding Scope */
private final Map scopes = new HashMap();
/** Map from alias to canonical bean name */
private final Map aliasMap = CollectionFactory.createConcurrentMapIfPossible(16);
/** Map from bean name to merged RootBeanDefinition */
private final Map mergedBeanDefinitions = CollectionFactory.createConcurrentMapIfPossible(16);
/** Names of beans that have already been created at least once */
private final Set alreadyCreated = Collections.synchronizedSet(new HashSet());
/** Names of beans that are currently in creation */
private final ThreadLocal prototypesCurrentlyInCreation = new ThreadLocal();
/** Cache of singleton objects created by FactoryBeans: FactoryBean name --> object */
private final Map factoryBeanObjectCache = new HashMap();
/**
* Create a new AbstractBeanFactory.
*/
public AbstractBeanFactory() {
}
/**
* Create a new AbstractBeanFactory with the given parent.
* @param parentBeanFactory parent bean factory, or <code>null</code> if none
* @see #getBean
*/
public AbstractBeanFactory(BeanFactory parentBeanFactory) {
this.parentBeanFactory = parentBeanFactory;
}
//---------------------------------------------------------------------
// Implementation of BeanFactory interface
//---------------------------------------------------------------------
public Object getBean(String name) throws BeansException {
return getBean(name, null, null);
}
public Object getBean(String name, Class requiredType) throws BeansException {
return getBean(name, requiredType, null);
}
/**
* Return an instance, which may be shared or independent, of the specified bean.
* @param name the name of the bean to retrieve
* @param args arguments to use if creating a prototype using explicit arguments to a
* static factory method. It is invalid to use a non-null args value in any other case.
* @return an instance of the bean
* @throws BeansException if the bean could not be created
*/
public Object getBean(String name, Object[] args) throws BeansException {
return getBean(name, null, args);
}
/**
* Return an instance, which may be shared or independent, of the specified bean.
* @param name the name of the bean to retrieve
* @param requiredType the required type of the bean to retrieve
* @param args arguments to use if creating a prototype using explicit arguments to a
* static factory method. It is invalid to use a non-null args value in any other case.
* @return an instance of the bean
* @throws BeansException if the bean could not be created
*/
public Object getBean(String name, Class requiredType, final Object[] args) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean = null;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
if (containsBeanDefinition(beanName)) {
RootBeanDefinition mbd = getMergedBeanDefinition(beanName, false);
bean = getObjectForBeanInstance(sharedInstance, name, mbd);
}
else {
bean = getObjectForBeanInstance(sharedInstance, name, null);
}
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
// Delegation to parent with args only possible for AbstractBeanFactory.
return ((AbstractBeanFactory) parentBeanFactory).getBean(nameToLookup, requiredType, args);
}
else if (args == null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
throw new NoSuchBeanDefinitionException(beanName,
"Cannot delegate to parent BeanFactory because it does not supported passed-in arguments");
}
}
this.alreadyCreated.add(beanName);
final RootBeanDefinition mbd = getMergedBeanDefinition(beanName, false);
checkMergedBeanDefinition(mbd, beanName, args);
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope = (Scope) this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
Object bean = createBean(beanName, mbd, args);
if (requiresDestruction(bean, mbd)) {
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors()));
}
return bean;
}
finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; " +
"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return bean;
}
public boolean containsBean(String name) {
String beanName = transformedBeanName(name);
if (containsSingleton(beanName) || containsBeanDefinition(beanName)) {
return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
}
// Not found -> check parent.
BeanFactory parentBeanFactory = getParentBeanFactory();
return (parentBeanFactory != null && parentBeanFactory.containsBean(originalBeanName(name)));
}
public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
String beanName = transformedBeanName(name);
Object beanInstance = getSingleton(beanName);
if (beanInstance != null) {
if (beanInstance instanceof FactoryBean) {
return (BeanFactoryUtils.isFactoryDereference(name) || ((FactoryBean) beanInstance).isSingleton());
}
else {
return !BeanFactoryUtils.isFactoryDereference(name);
}
}
else {
// No singleton instance found -> check bean definition.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// No bean definition found in this factory -> delegate to parent.
return parentBeanFactory.isSingleton(originalBeanName(name));
}
RootBeanDefinition bd = getMergedBeanDefinition(beanName, false);
// In case of FactoryBean, return singleton status of created object if not a dereference.
if (bd.isSingleton()) {
if (isBeanClassMatch(beanName, bd, FactoryBean.class)) {
if (BeanFactoryUtils.isFactoryDereference(name)) {
return true;
}
FactoryBean factoryBean = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
return factoryBean.isSingleton();
}
else {
return !BeanFactoryUtils.isFactoryDereference(name);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -