zoukankan      html  css  js  c++  java
  • Spring IOC容器分析(3) -- DefaultListableBeanFactory

    上一节介绍了封装bean对象的BeanDefinition接口。从前面小结对BeanFactory的介绍中,我们知道bean对象是存储在map中,通过调用getBean方法可以得到bean对象。在接口BeanFactory中定义了多个相同签名的getBean方法,如下所示:

    	Object getBean(String name) throws BeansException;
    
    	<T> T getBean(String name, Class<T> requiredType) throws BeansException;
    
    	<T> T getBean(Class<T> requiredType) throws BeansException;
    
    	Object getBean(String name, Object... args) throws BeansException;
    
    	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
    

    DefaultListableBeanFactory

    DefaultListableBeanFactory是Bean工厂的一个默认实现,我们可以对它进行拓展以便实现自定义的Bean工厂。作为默认的Bean工厂实现,肯定也实现了接口中定义的getBean方法。截取DefaultListableBeanFactory中与getBean方法相关的源码如下:

    public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
    		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    	
    	......
    	
    	@Override
    	public <T> T getBean(Class<T> requiredType) throws BeansException {
    		return getBean(requiredType, (Object[]) null);
    	}
    
    	@Override
    	public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
    		NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args);
    		if (namedBean != null) {
    			return namedBean.getBeanInstance();
    		}
    		BeanFactory parent = getParentBeanFactory();
    		if (parent != null) {
    			return parent.getBean(requiredType, args);
    		}
    		throw new NoSuchBeanDefinitionException(requiredType);
    	}
    	
    	......
    	
    }
    

    发现DefaultListableBeanFactory中只实现了两个getBean接口,BeanFactory中总共有五个接口,那另外三个接口呢?在哪里实现的?尤其是最重要的getBean(String name)接口。

    查看DefaultListableBeanFactory类UML类图关系发现有一个AbstractBeanFactory抽象类,DefaultListableBeanFactory继承了AbstractBeanFactory,如下图所示:

    DefaultListableBeanFactoryUML类图关系

    AbstractBeanFactory

    通过查找AbstractBeanFactory源码,终于找到BeanFactory接口中另外三个getBean方法的实现。源码如下:

    package org.springframework.beans.factory.support;
    
    import java.beans.PropertyEditor;
    import java.security.AccessControlContext;
    import java.security.AccessController;
    import java.security.PrivilegedAction;
    import java.security.PrivilegedActionException;
    import java.security.PrivilegedExceptionAction;
    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.LinkedHashMap;
    import java.util.LinkedHashSet;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.ConcurrentHashMap;
    
    import org.springframework.beans.BeanUtils;
    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.TypeMismatchException;
    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.FactoryBean;
    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.BeanDefinitionHolder;
    import org.springframework.beans.factory.config.BeanExpressionContext;
    import org.springframework.beans.factory.config.BeanExpressionResolver;
    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.DecoratingClassLoader;
    import org.springframework.core.NamedThreadLocal;
    import org.springframework.core.ResolvableType;
    import org.springframework.core.convert.ConversionService;
    import org.springframework.util.Assert;
    import org.springframework.util.ClassUtils;
    import org.springframework.util.ObjectUtils;
    import org.springframework.util.StringUtils;
    import org.springframework.util.StringValueResolver;
    
    public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
    	
      	......
          
    	@Override
    	public Object getBean(String name) throws BeansException {
    		return doGetBean(name, null, null, false);
    	}
    
    	@Override
    	public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
    		return doGetBean(name, requiredType, null, false);
    	}
    
    	@Override
    	public Object getBean(String name, Object... args) throws BeansException {
    		return doGetBean(name, null, args, false);
    	}
    
    	public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {
    		return doGetBean(name, requiredType, args, false);
    	}
    
    	@SuppressWarnings("unchecked")
    	protected <T> T doGetBean(
    			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
    			throws BeansException {
    
    		final String beanName = transformedBeanName(name);
    		Object bean;
    
    		// Eagerly check singleton cache for manually registered singletons.
    		Object sharedInstance = getSingleton(beanName);
    		if (sharedInstance != null && args == 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 + "'");
    				}
    			}
    			bean = getObjectForBeanInstance(sharedInstance, name, beanName, 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 (args != null) {
    					// Delegation to parent with explicit args.
    					return (T) parentBeanFactory.getBean(nameToLookup, args);
    				}
    				else {
    					// No args -> delegate to standard getBean method.
    					return parentBeanFactory.getBean(nameToLookup, requiredType);
    				}
    			}
    
    			if (!typeCheckOnly) {
    				markBeanAsCreated(beanName);
    			}
    
    			try {
    				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    				checkMergedBeanDefinition(mbd, beanName, args);
    
    				// Guarantee initialization of beans that the current bean depends on.
    				String[] dependsOn = mbd.getDependsOn();
    				if (dependsOn != null) {
    					for (String dep : dependsOn) {
    						if (isDependent(beanName, dep)) {
    							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
    						}
    						registerDependentBean(dep, beanName);
    						getBean(dep);
    					}
    				}
    
    				// Create bean instance.
    				if (mbd.isSingleton()) {
    					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
    						@Override
    						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, beanName, 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, beanName, mbd);
    				}
    
    				else {
    					String scopeName = mbd.getScope();
    					final Scope scope = this.scopes.get(scopeName);
    					if (scope == null) {
    						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
    					}
    					try {
    						Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
    							@Override
    							public Object getObject() throws BeansException {
    								beforePrototypeCreation(beanName);
    								try {
    									return createBean(beanName, mbd, args);
    								}
    								finally {
    									afterPrototypeCreation(beanName);
    								}
    							}
    						});
    						bean = getObjectForBeanInstance(scopedInstance, name, beanName, 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);
    					}
    				}
    			}
    			catch (BeansException ex) {
    				cleanupAfterBeanCreationFailure(beanName);
    				throw ex;
    			}
    		}
    
    		// Check if required type matches the type of the actual bean instance.
    		if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
    			try {
    				return getTypeConverter().convertIfNecessary(bean, requiredType);
    			}
    			catch (TypeMismatchException ex) {
    				if (logger.isDebugEnabled()) {
    					logger.debug("Failed to convert bean '" + name + "' to required type '" +
    							ClassUtils.getQualifiedName(requiredType) + "'", ex);
    				}
    				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    			}
    		}
    		return (T) bean;
    	}
      
      	......
    }
    

    在三个相同签名getBean方法中,均调用doGetBean方法。doGetBean方法负责从Bean工厂中获取bean对象的具体实现,下面来看看该方法的具体实现:

    1. 检查手动注册的单例集合缓存中是否含有该bean对象,若有,则取出返回,否则继续执行;
    2. 检查该bean是否已经创建,从而判断是否属于循环引用,若是,抛出异常返回,否则继续执行;
    3. 判断bean工厂中是否存在该bean definition,若存在,则取出返回,否则继续执行;
    4. 初始化该bean所依赖的bean对象;
    5. 判断该bean是否是单例模式(singleton),若是,创建单例对象,否则继续执行;
    6. 判断该bean是否是原型模式(prototype),若是,创建原型对象,否则继续执行;
    7. 创建自定义类型(scope)bean对象。

    从上面对doGetBean方法分析,可看出创建并获取bean对象是一个非常复杂的过程,并不是简简单单的放入Map中再从其中取出。

    小结

    本文对IOC容器的核心getBean()方法作了简单的分析,初步了解了IOC容器中getBean()方法的执行流程原理,这对于帮助我们理解IOC容器是十分有帮助的。目前对IOC机制的各个模块都有了一定的了解,下面可以综合各个模块,串联起来研究IOC依赖注入的完整流程。

    下文将以ClassPathXmlApplicationContext作为xml文件加载器,实现Spring IOC的类加载,通过断点跟踪来了解IOC对象注入完整流程

  • 相关阅读:
    从‘void*’到‘int’的转换损失精度
    ../lib//libscsdblog.so: undefined reference to `pthread_atfork'
    使用Crypto++库的CBC模式实现加密
    VIM常用命令
    mysql bin-log三种模式
    windows64位Oracle安装和PL/SQL配置
    Maven项目中突然找不到Build Path或maven dependencies library
    org.springframework.beans.factory.config.MethodInvokingFactoryBean的使用
    使用Spring的StingUtils的commaDelimitedListToStringArray来获取字符串数组
    Spring注入
  • 原文地址:https://www.cnblogs.com/hthuang/p/7831305.html
Copyright © 2011-2022 走看看