博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring源码学习(一)DefaultListableBeanFactory
阅读量:2491 次
发布时间:2019-05-11

本文共 24608 字,大约阅读时间需要 82 分钟。

1、示例POJO类

用户类User,其中包含一个狗的引用

package org.springframework.cn.shu.edu.pojo;public class User {    String username;    String password;    Dog dog;    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    public String getPassword() {        return password;    }    public void setPassword(String password) {        this.password = password;    }    public Dog getDog() {        return dog;    }    public void setDog(Dog dog) {        this.dog = dog;    }}

 

狗类

package org.springframework.cn.shu.edu.pojo;public class Dog {    String name;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}

2、工程结构

3、spring配置文件beans.xml

其中配置了一个Dog类的对象,一个User类的对象。

 

4、测试代码

import org.springframework.beans.factory.support.DefaultListableBeanFactory;import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;import org.springframework.cn.shu.edu.pojo.User;import org.springframework.core.io.ClassPathResource;import org.springframework.core.io.Resource;public class Test1 {    public static void main(String[] args) {        Resource res = new ClassPathResource("beans.xml");        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);        reader.loadBeanDefinitions(res);        User chenjie = factory.getBean("chenjie", User.class);        System.out.println(chenjie.getUsername());        User chenjie2 = factory.getBean("chenjie", User.class);        System.out.println(chenjie2.getDog().getName());    }}

其中,首先定义了一个资源,指定从classpath下加载beans.xml文件,然后新建了一个DefaultListableBeanFactory的工厂对象,然后新建了一个XmlBeanDefinitionReader的Xml类定义读取器,接着使用该读取器加载bean定义。

随后便可以使用创建的工厂了,我们调用两次getBean。

首先观看输出:

可以看到User类中的Dog类对象的引用两次都没有找到,而User类第一次没有找到,第二次找到了。我们将分析整个过程。

 

5、

Resource res = new ClassPathResource("beans.xml");

此句新建了一个ClassPathResource对象,用beans.xml作为参数。看看ClassPathResource的类图 

Resource是Spring用来封装IO操作的类。在这里我们的BeanDefinition信息是以xml文件形式存在的。

这句代码首先调用了一个参数的构造函数,参数为bean定义的配置文件的路径

public ClassPathResource(String path) {		this(path, (ClassLoader) null);	}

可以看到它又调用了两个参数的构造函数,其中第二个参数为ClassLoader类型,这里由于此前没有指定ClassLoader是谁,因此设置为空。

再看看两个参数的构造函数

public ClassPathResource(String path, ClassLoader classLoader) {		//判空		Assert.notNull(path, "Path must not be null");		//清洗路径		String pathToUse = StringUtils.cleanPath(path);		if (pathToUse.startsWith("/")) {			pathToUse = pathToUse.substring(1);		}		this.path = pathToUse;		//得到classLoader		this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());	}

首先由于必须给定配置文件的路径,因此使用了断言来判空。

然后使用StringUtils工具类的cleanPath方法进行路径的整理。

public static String cleanPath(String path) {		if (path == null) {			return null;		}		String pathToUse = replace(path, WINDOWS_FOLDER_SEPARATOR, FOLDER_SEPARATOR);		// Strip prefix from path to analyze, to not treat it as part of the		// first path element. This is necessary to correctly parse paths like		// "file:core/../core/io/Resource.class", where the ".." should just		// strip the first "core" directory while keeping the "file:" prefix.		int prefixIndex = pathToUse.indexOf(":");		String prefix = "";		if (prefixIndex != -1) {			prefix = pathToUse.substring(0, prefixIndex + 1);			pathToUse = pathToUse.substring(prefixIndex + 1);		}		if (pathToUse.startsWith(FOLDER_SEPARATOR)) {			prefix = prefix + FOLDER_SEPARATOR;			pathToUse = pathToUse.substring(1);		}		String[] pathArray = delimitedListToStringArray(pathToUse, FOLDER_SEPARATOR);		List
pathElements = new LinkedList
(); int tops = 0; for (int i = pathArray.length - 1; i >= 0; i--) { String element = pathArray[i]; if (CURRENT_PATH.equals(element)) { // Points to current directory - drop it. } else if (TOP_PATH.equals(element)) { // Registering top path found. tops++; } else { if (tops > 0) { // Merging path element with element corresponding to top path. tops--; } else { // Normal path element found. pathElements.add(0, element); } } } // Remaining top paths need to be retained. for (int i = 0; i < tops; i++) { pathElements.add(0, TOP_PATH); } return prefix + collectionToDelimitedString(pathElements, FOLDER_SEPARATOR); }

整理完成以后,判断路径是否以/开头,如果是/开头,则表示是相对于classpath是根目录,所以用/后面的作为路径。

然后判断classloader是否为空,如果传入的不为空则使用之,如果为空,则调用ClassUtils.getDefaultClassLoader()来获取默认的ClassLoader,其方法如下。

public static ClassLoader getDefaultClassLoader() {		ClassLoader cl = null;		try {			cl = Thread.currentThread().getContextClassLoader();		}		catch (Throwable ex) {			// Cannot access thread context ClassLoader - falling back to system class loader...		}		if (cl == null) {			// No thread context class loader -> use class loader of this class.			cl = ClassUtils.class.getClassLoader();		}		return cl;	}

首先尝试得到当前线程的上下文的ClassLoader,如果获取失败会抛出异常,cl为空,则会获取ClassUtil类对象的ClassLoader并返回。

 

6、

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

首先看看DefaultListableBeanFactory的类图。

可以看到是一个相对复杂的继承关系。

首先调用DefaultListableBeanFactory类的无参构造函数。

/**	 * Create a new DefaultListableBeanFactory.	 */	public DefaultListableBeanFactory() {		super();		logger.info("初始化DefaultListableBeanFactory完成");	}

可以看到什么都没有做,只是调用了父类的无参构造函数。我们来看看它的父类AbstractAutowireCapableBeanFactory的无参构造函数。

/**	 * Create a new AbstractAutowireCapableBeanFactory.	 */	public AbstractAutowireCapableBeanFactory() {		super();		logger.info("初始化AbstractAutowireCapableBeanFactory()完成");		ignoreDependencyInterface(BeanNameAware.class);		ignoreDependencyInterface(BeanFactoryAware.class);		ignoreDependencyInterface(BeanClassLoaderAware.class);	}

可以看到其调用了父类的无参构造函数,接着调用了三次ignoreDependencyInterface方法,该方法其作用是指定自动装配(autowiring)的时候忽略的接口。这里我们先不做讨论。

我们来看看其调用的父类AbstractBeanFactory的无参构造函数

/**	 * Create a new AbstractBeanFactory.	 */	public AbstractBeanFactory() {		logger.info("初始化AbstractBeanFactory()完成");	}

其中什么都没有做。到这里没有再显式地调用父类的构造函数,事实上,当我们再看AbstractBeanFactory的父类FactoryBeanRegistrySupport,FactoryBeanRegistrySupport的父类DefaultSingletonBeanRegistry,DefaultSingletonBeanRegistry的父类SimpleAliasRegistry的源码会发现其都没有写构造方法,也就是说其都是默认的空的无参构造函数。

 

7、

XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);

这里新建一个XmlBeanDefinitionReader对象,并以此前创建的DefaultListableBeanFactory的对象factory作为参数。

public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {		super(registry);		logger.info("初始化XmlBeanDefinitionReader()完成");	}

再看其构造器,发现需要的参数只需要实现BeanDefinitionRegistry 接口即可,观察类图或者查看源码可知DefaultListableBeanFactory实现了BeanDefinitionRegistry接口

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory      implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {}

该接口中有bean定义数量和bean定义名称两个属性,有注册bean定义、移除bean定义,得到bean定义、判断是否包含bean定义、bean名称是否在使用等方法。

XmlBeanDefinitionReader调用了父类的构造器如下:

protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");		this.registry = registry;		// Determine ResourceLoader to use.		if (this.registry instanceof ResourceLoader) {			logger.info("this.registry instanceof ResourceLoader" );			this.resourceLoader = (ResourceLoader) this.registry;		}		else {			logger.info("this.registry is not instanceof ResourceLoader" );			this.resourceLoader = new PathMatchingResourcePatternResolver();		}	}

首先进行必要的判空和赋值,然后判断传入的参数(这个registry对象参数肯定实现了BeanDefinitionRegistry ,但是否实现了ResourceLoader未知)是否实现了ResourceLoader。

我们这里传入的DefaultListableBeanFactory对象没有实现这个接口,因此在else里面,会新建一个PathMatchingResourcePatternResolver对象。

ResourceLoader提供 classpath下单资源文件的载入,而ResourcePatternResolver提供了多资源文件的载入。ResourcePatternResolver有一个实现类:PathMatchingResourcePatternResolver

我们这里新建了一个PathMatchingResourcePatternResolver对象。我们先不深入。

 

7、

reader.loadBeanDefinitions(res);

这里使用了XmlBeanDefinitionReader类的loadBeanDefinitions方法加载Resource类的对象res。

/**	 * Load bean definitions from the specified XML file.	 * @param resource the resource descriptor for the XML file	 * @return the number of bean definitions found	 * @throws BeanDefinitionStoreException in case of loading or parsing errors	 */	public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {		logger.info("进入loadBeanDefinitions(Resource resource)");		return loadBeanDefinitions(new EncodedResource(resource));	}

这里首先将resource进行encode,作用是进行编码。然后我们看看loadBeanDefinitions的具体实现。

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {		logger.info("进入loadBeanDefinitions(EncodedResource encodedResource)");		Assert.notNull(encodedResource, "EncodedResource must not be null");		if (logger.isInfoEnabled()) {			logger.info("Loading XML bean definitions from " + encodedResource.getResource());		}		Set
currentResources = this.resourcesCurrentlyBeingLoaded.get(); if (currentResources == null) { currentResources = new HashSet
(4); this.resourcesCurrentlyBeingLoaded.set(currentResources); } if (!currentResources.add(encodedResource)) { throw new BeanDefinitionStoreException( "Detected cyclic loading of " + encodedResource + " - check your import definitions!"); } try { InputStream inputStream = encodedResource.getResource().getInputStream(); try { InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); } return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); } finally { inputStream.close(); } } catch (IOException ex) { throw new BeanDefinitionStoreException( "IOException parsing XML document from " + encodedResource.getResource(), ex); } finally { currentResources.remove(encodedResource); if (currentResources.isEmpty()) { this.resourcesCurrentlyBeingLoaded.remove(); } } }

进行必要的判空后,首先使用

Set
currentResources = this.resourcesCurrentlyBeingLoaded.get();
XmlBeanDefinitionReader内部维护了一个resourcesCurrentlyBeingLoaded变量,用于保存最近被加载的资源。private final ThreadLocal
> resourcesCurrentlyBeingLoaded = new NamedThreadLocal
>("XML bean definition resources currently being loaded");

如果为空,则进行必要的初始化。

然后将传入的参数加入currentResources中,紧接着得到资源里面的输入流(public interface Resource extends InputStreamSource):

InputStream inputStream = encodedResource.getResource().getInputStream();

然后将输入流封装成了org.xml.sax库的InputSource对象,这里完成对xml的解析的加载过程。然后进行编码设置。

接着调用了doLoadBeanDefinitions(inputSource, encodedResource.getResource());方法。

做完以后关闭流,最后将传入的资源从最近被加载的资源中删除。

我们来看看doLoadBeanDefinitions方法的实现。

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {		try {			int validationMode = getValidationModeForResource(resource);			Document doc = this.documentLoader.loadDocument(					inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());			return registerBeanDefinitions(doc, resource);		}//....}
其中涉及validationMode验证模式,可以参考https://blog.csdn.net/nangongyanya/article/details/53887467

然后使用this.documentLoader.loadDocument方法来加载xml文档。documentLoader是DefaultDocumentLoader类的对象。

private DocumentLoader documentLoader = new DefaultDocumentLoader();

让我们来看看DefaultDocumentLoader类的loadDocument方法。

public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,			ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {		DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);		if (logger.isDebugEnabled()) {			logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");		}		DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);		return builder.parse(inputSource);	}

它有几个参数,分别是输入源inputSource,实体解析器entityResolver,错误处理器errorHandler,XML验证模式validationMode,namespaceAware。最终落实到DocumentBuilder的parse方法。

接着调用registerBeanDefinitions(doc, resource);

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {		// Read document based on new BeanDefinitionDocumentReader SPI.		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();		int countBefore = getRegistry().getBeanDefinitionCount();		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));		return getRegistry().getBeanDefinitionCount() - countBefore;	}

其中createBeanDefinitionDocumentReader方法主要新建了一个BeanDefinitionDocumentReader 接口的实现类DefaultBeanDefinitionDocumentReader然后调用其registerBeanDefinitions方法

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {		this.readerContext = readerContext;		logger.info("---->Loading bean definitions at " + DefaultBeanDefinitionDocumentReader.class.getSimpleName());		Element root = doc.getDocumentElement();		logger.info("--->root:" + root.getTagName());		BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);		preProcessXml(root);		parseBeanDefinitions(root, delegate);		postProcessXml(root);	}

其中root代表了xml文档的根元素,可以增加打印语句看看:

从输出可以看到其根元素为<beans></beans>

接着Bean定义解析代理类BeanDefinitionParserDelegate的对象,由它解析根元素中的内容,对于根元素前和跟元素后的内容,则由preProcessXml和postProcessXml两个方法完成,目前为空实现。我们来看看parseBeanDefinitions方法。

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {		if (delegate.isDefaultNamespace(root)) {			NodeList nl = root.getChildNodes();			for (int i = 0; i < nl.getLength(); i++) {				Node node = nl.item(i);				if (node instanceof Element) {					Element ele = (Element) node;					if (delegate.isDefaultNamespace(ele)) {						parseDefaultElement(ele, delegate);					}					else {						delegate.parseCustomElement(ele);					}				}			}		}		else {			delegate.parseCustomElement(root);		}	}

首先判断是否是默认的命名空间,如果是,则执行parseDefaultElement,否则执行parseCustomElement。

我们这里是使用的默认的命名空间,因此接着调用getChildNodes方法获得<beans></beans>下面的子节点,也就是<bean></bean>。

然后对于每个子节点,根据当前是否是默认命名空间来调用不同方法解析。

我们这里先只看parseDefaultElement。

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {			importBeanDefinitionResource(ele);		}		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {			processAliasRegistration(ele);		}		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {			processBeanDefinition(ele, delegate);		}	}

这里分了3种情况,分别是节点标签名对应import alias 和bean的情况。

它们分别处理<import/> <alias/>和<bean/>

我们这里只涉及bean的解析。来看看。

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {		/***		 * BeanDefinitionHolder是BeanDefinition对象的封装类,封装了BeanDefinition,Bean的名字和别名。用它来完成向IoC容器注册。		 * 得到这个BeanDefinition实际上就意味着获得了BeanDefinition,是通过BeanDefinitionParserDelegate对XML元素的信息按照		 * Spring的Bean规则进行解析得到的		 */		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);		if (bdHolder != null) {			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);			try {				// 这里是向IoC容器注册解析得到的BeanDefinition的地方。				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());			}			catch (BeanDefinitionStoreException ex) {				getReaderContext().error("Failed to register bean definition with name '" +						bdHolder.getBeanName() + "'", ele, ex);			}			// 发送注册事件			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));		}	}

BeanDefinitionHolder是BeanDefinition的封装。

而BeanDefinition可以看成是<bean>定义的抽象。

可以看到其中包含关于类名、原型、延迟加载、单例、依赖的方法。

具体的加载过程由BeanDefinitionParserDelegate对XML元素的信息按照Spring的Bean规则进行解析得到的,入口是

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean){}

其中会调用parseBeanDefinitionElement方法。

public AbstractBeanDefinition parseBeanDefinitionElement(			Element ele, String beanName, BeanDefinition containingBean) {		logger.info("\tgo into parseBeanDefinitionElement of beanName :" + beanName);		this.parseState.push(new BeanEntry(beanName));		String className = null;		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();			logger.info("\tclass =" + className);		}		try {			String parent = null;			//如果元素有parent属性			if (ele.hasAttribute(PARENT_ATTRIBUTE)) {				//得到parent节点				parent = ele.getAttribute(PARENT_ATTRIBUTE);			}			//根据parent创建AbstractBeanDefinition			AbstractBeanDefinition bd = createBeanDefinition(className, parent);			//解析bean定义			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);			//为bean定义设置描述			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));			parseMetaElements(ele, bd);			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());			//解析构造器参数元素			parseConstructorArgElements(ele, bd);			//解析属性元素			parsePropertyElements(ele, bd);			parseQualifierElements(ele, bd);			bd.setResource(this.readerContext.getResource());			bd.setSource(extractSource(ele));			return bd;		}		catch (ClassNotFoundException ex) {			error("Bean class [" + className + "] not found", ele, ex);		}		catch (NoClassDefFoundError err) {			error("Class that bean class [" + className + "] depends on not found", ele, err);		}		catch (Throwable ex) {			error("Unexpected failure during bean definition parsing", ele, ex);		}		finally {			this.parseState.pop();		}		return null;	}

其中createBeanDefinition创建一个BeanDefinition的实现GenericBeanDefinition。然后调用parseConstructorArgElements、parsePropertyElements等解析构造器参数,解析属性元素等。

createBeanDefinition中直接使用BeanDefinitionReaderUtils.createBeanDefinition创建bean。
public static AbstractBeanDefinition createBeanDefinition(			String parentName, String className, ClassLoader classLoader) throws ClassNotFoundException {		GenericBeanDefinition bd = new GenericBeanDefinition();		bd.setParentName(parentName);		if (className != null) {			if (classLoader != null) {				bd.setBeanClass(ClassUtils.forName(className, classLoader));			}			else {				bd.setBeanClassName(className);			}		}		return bd;	}

其中使用了ClassUtils加载类的定义,然后为BeanDefinition设置了bean的class属性。

parsePropertyElements中循环调用了多次parsePropertyElement来处理每个property

与XML中定义一致。

 

然后回到:DefaultBeanDefinitionDocumentReader

解析bean定义后,使用如下方法注册bean定义,这里的getReaderContext().getRegistry()就是最开始新建的工厂对象DefaultListableBeanFactory。

BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

主要代码如下,即调用registerBeanDefinition方法。

该方法主要是往一个并发HashMap中写入刚刚注册得到的bean定义

private final Map
beanDefinitionMap = new ConcurrentHashMap
();

由此,便将bean名字到bean定义的映射保存在了DefaultListableBeanFactory中。

8、

User chenjie = factory.getBean("chenjie", User.class);

这里调用了DefaultListableBeanFactory的getBean方法,但该方法是从父类AbstractBeanFactory继承而来。

public 
T getBean(String name, Class
requiredType) throws BeansException { logger.info("AbstractBeanFactory getBean,name=" + name + ",requiredType=" + requiredType); return doGetBean(name, requiredType, null, false); }

直接调用doGetBean

protected 
T doGetBean( final String name, final Class
requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { logger.info("AbstractBeanFactory doGetBean,name=" + name + ",requiredType=" + requiredType); final String beanName = transformedBeanName(name); logger.info("transformedBeanName, beanName=" + beanName); Object bean; // Eagerly check singleton cache for manually registered singletons. //先从缓存中去取,处理已经被创建过的单件模式的bean,对这种bean的请求不需要重复地创建 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { logger.info("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 + "'"); } } /*** * 这里的getObjectForBeanInstance完成的是FactoryBean的相关处理, * 以取得FactoryBean的生产结果,BeanFactory和FactoryBean的区别 * 会在这个过程中详细地分析 */ bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { logger.info("sharedInstance == null || args != null"); // 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. /** * 这里对IoC容器里的BeanDefinition是否存在进行检查,检查是否能在当前的BeanFactory中取到我们需要的bean。 * 如果在当前的工厂中取不到,则到双亲BeanFactory中去取; * 如果当前的双亲工厂取不到,那就顺着双亲BeanFactory链一直向上查找 */ 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); } //这里根据bean的名字取得BeanDefinition final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. /*** * 取当前bean的所有依赖bean,这样会触发getBean的递归调用,直至取到一个没有任何依赖的bean为止。 */ String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dependsOnBean : dependsOn) { getBean(dependsOnBean); registerDependentBean(dependsOnBean, beanName); } } // Create bean instance. /*** * 这里创建Singleton bean的实例,通过调用crateBean方法,这里有个回调函数getObject, * 会在getSingleton中调用ObjectFactory的createBean */ 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, beanName, mbd); } //这里是创建prototype bean的地方 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 '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, new ObjectFactory() { 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); } } } // Check if required type matches the type of the actual bean instance. /*** * 这里对创建出来的bean进行类型检查,如果没有问题,就返回这个新创建出来的bean, * 这个bean已经是包含了依赖关系的bean */ 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; }

总结:

你可能感兴趣的文章
Swift code into Object-C 出现 ***-swift have not found this file 的问题
查看>>
为什么你的App介绍写得像一坨翔?
查看>>
RTImageAssets插件--@3x可自动生成@2x图片
查看>>
iOS开发的一些奇巧淫技
查看>>
常浏览的博客和网站
查看>>
Xcode 工程文件打开不出来, cannot be opened because the project file cannot be parsed.
查看>>
iOS在Xcode6中怎么创建OC category文件
查看>>
5、JavaWeb学习之基础篇—标签(自定义&JSTL)
查看>>
8、JavaWEB学习之基础篇—文件上传&下载
查看>>
reRender属性的使用
查看>>
href="javascript:void(0)"
查看>>
h:panelGrid、h:panelGroup标签学习
查看>>
f:facet标签 的用法
查看>>
<h:panelgroup>相当于span元素
查看>>
java中append()的方法
查看>>
必学高级SQL语句
查看>>
经典SQL语句大全
查看>>
log日志记录是什么
查看>>
<rich:modelPanel>标签的使用
查看>>
<h:commandLink>和<h:inputLink>的区别
查看>>