Spring中BeanDefinition的探索

        在之前探索创建Bean的过程中,我们看到一个出现很频繁的类,RootBeanDefinition。该类中存储了一个bean的所有信息,后续创建Bean对象就是根据一个bean的BeanDefinition,然后通过反射创建的。该类的类关系图如下:

从图中可知,RootBeanDefinition是BeanDefinition的一个实现类。既然后续创建需要用到RootBeanDefinition,那么肯定在使用之前就得创建出来才行。我们本文就来探究一下RootBeanDefinition的创建过程。我们采用的还是debug断点调试法来一步一步探索,因为上一篇文章中前面几个步骤已经探索过了,我们本文中就直接从 refresh() 方法开始调试。

1. 阅读refresh()源码

refresh()方法的源码如下:

public void refresh() throws BeansException, IllegalStateException {
	synchronized(this.startupShutdownMonitor) {
		StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
		this.prepareRefresh();
		ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
		this.prepareBeanFactory(beanFactory);

		try {
			this.postProcessBeanFactory(beanFactory);
			StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
			this.invokeBeanFactoryPostProcessors(beanFactory);
			this.registerBeanPostProcessors(beanFactory);
			beanPostProcess.end();
			this.initMessageSource();
			this.initApplicationEventMulticaster();
			this.onRefresh();
			this.registerListeners();
			this.finishBeanFactoryInitialization(beanFactory);
			this.finishRefresh();
		} catch (BeansException var10) {
			if (this.logger.isWarnEnabled()) {
				this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
			}

			this.destroyBeans();
			this.cancelRefresh(var10);
			throw var10;
		} finally {
			this.resetCommonCaches();
			contextRefresh.end();
		}

	}
}

首先需要明白一个点的是,spring使用beanFactory来创建对象,创建时使用BeanDefinition通过反射来创建,所以BeanDefinition的创建肯定是在创建了beanFactory之后或者创建过程中创建的,所以创建过程可以从obtainFreshBeanFactory()开始看。

2. obtainFreshBeanFactory()源码阅读

obtainFreshBeanFactory()的源码较为简单,源码如下:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
	this.refreshBeanFactory();
	return this.getBeanFactory();
}

其中getBeanFactory()是一个获取Beanfactory的方法,不会创建BeanDefinition。所以需要阅读refreshBeanFactory()方法的源码

3. refreshBeanFactory()源码阅读

该方法是AbstractApplicationContext中定义的一个抽象方法,其方法实现类有两个,一个是AbstractRefreshableApplicationContext,另外一个是GenericApplicationContext,根据debug进入方法知道,逻辑是进入AbstractRefreshableApplicationContext的方法实现中。我们继续阅读。以上分析的部分,因为逻辑不是很复杂,就不debug测试,但是在AbstractRefreshableApplicationContext的refreshBeanFactory()方法中存在多个逻辑步骤,我将一步一步debug进行分析。refreshBeanFactory()源码如下:

protected final void refreshBeanFactory() throws BeansException {
	if (this.hasBeanFactory()) {
		this.destroyBeans();
		this.closeBeanFactory();
	}

	try {
        //创建beanFactory
		DefaultListableBeanFactory beanFactory = this.createBeanFactory();
		beanFactory.setSerializationId(this.getId());
		this.customizeBeanFactory(beanFactory);
        //加载BeanDefinition,该方法用于加载配置文件中的bean信息
		this.loadBeanDefinitions(beanFactory);
		this.beanFactory = beanFactory;
	} catch (IOException var2) {
		throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var2);
	}
}

执行完this.createBeanFactory()之后得到的对象信息如下:

 当执行完this.loadBeanDefinitions(beanFactory)方法后,beanDefinitionMap和beanDefinitionNames就存在值了,可得出结论是,我们定义的User类的beanDefinition信息是在执行完loadBeanDefinitions(beanFactory)方法后加载的,效果如下:

所以我们需要继续查看this.loadBeanDefinitions(beanFactory)的方法源码。

4. loadBeanDefinitions(beanFactory)源码阅读

该方法中的代码逻辑不是很复杂,其中创建了XmlBeanDefinitionReader对象,从命名理解,该类是一个beanDefinition的读取类,然后是对该类进行一些属性设置,对应的源码如下:

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    //创建XmlBeanDefinitionReader对象
	XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
	/**设置beanDefinitionReader的属性 start*/
	beanDefinitionReader.setEnvironment(this.getEnvironment());
	beanDefinitionReader.setResourceLoader(this);
	beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
	this.initBeanDefinitionReader(beanDefinitionReader);
	/**设置beanDefinitionReader的属性 end*/
	//该方法执行后,类信息被加载了
	this.loadBeanDefinitions(beanDefinitionReader);
}

该方法执行完this.loadBeanDefinitions(beanDefinitionReader)方法后,User类的信息就被加载了,执行效果如下:

所以我们得继续进入loadBeanDefinitions(beanDefinitionReader)方法中继续阅读相关的源码。

5. loadBeanDefinitions(beanDefinitionReader)源码阅读

loadBeanDefinitions(XmlBeanDefinitionReader reader)的源码如下:

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
	//路径是存储在configLocations,所以这个configResources是取不到值的
	Resource[] configResources = this.getConfigResources();
	if (configResources != null) {
		reader.loadBeanDefinitions(configResources);
	}
	//配置文件信息赋值给configLocations的逻辑是在ClassPathXmlApplicationContext的构造函数中的this.setConfigLocations(configLocations)中可以看出来
	String[] configLocations = this.getConfigLocations();
	if (configLocations != null) {
		//执行完后,类加载了
		reader.loadBeanDefinitions(configLocations);
	}
}

方法逻辑中,在执行完reader.loadBeanDefinitions(configLocations)后,bean信息被加载了,执行效果如下:

所以我们还得继续阅读XmlBeanDefinitionReader中的loadBeanDefinitions(configLocations)方法的源码。

6. XmlBeanDefinitionReader.loadBeanDefinitions(configLocations)源码阅读

loadBeanDefinitions(configLocations)的具体逻辑是在XmlBeanDefinitionReader的父类AbstractBeanDefinitionReader中。源码如下:

public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
	//这是一个断言,校验locations是否为null,locations是配置文件的数量,我这里只有一个配置文件,就是applicationContext.xml
	Assert.notNull(locations, "Location array must not be null");
	int count = 0;
	String[] var3 = locations;
	//var4的值是1
	int var4 = locations.length;

	for(int var5 = 0; var5 < var4; ++var5) {
		String location = var3[var5];
		//从代码逻辑上推断,类的信息肯定是在loadBeanDefinitions方法中加载的
		count += this.loadBeanDefinitions(location);
	}
	return count;
}

由于方法内部的逻辑较为简单,我们可以通过逻辑分析得到,类信息加载肯定是在loadBeanDefinitions(location)方法中,这里我们就直接继续阅读loadBeanDefinitions(location)方法的源码。

7. loadBeanDefinitions(String location)源码阅读

源码中是一个方法调用,源码如下:

public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
	return this.loadBeanDefinitions(location, (Set)null);
}

被调用的方法是loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources),对应的源码如下:

public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
	//resourceLoader不为null
	ResourceLoader resourceLoader = this.getResourceLoader();
	if (resourceLoader == null) {
		throw new BeanDefinitionStoreException("Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
	} else {
		int count;
		if (resourceLoader instanceof ResourcePatternResolver) {
			try {
				Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);
				//该方法执行后,Bean的信息就被加载了
				count = this.loadBeanDefinitions(resources);
				//入参传的是null,该逻辑不走
				if (actualResources != null) {
					Collections.addAll(actualResources, resources);
				}

				if (this.logger.isTraceEnabled()) {
					this.logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
				}

				return count;
			} catch (IOException var6) {
				throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", var6);
			}
		} else {
			Resource resource = resourceLoader.getResource(location);
			count = this.loadBeanDefinitions((Resource)resource);
			if (actualResources != null) {
				actualResources.add(resource);
			}

			if (this.logger.isTraceEnabled()) {
				this.logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
			}

			return count;
		}
	}
}

从源码中可知,我们还得往下继续阅读源码,真是很能绕啊。这里还可以用来看一个其他的知识点,类加载器。执行效果如图:

 这个类AppClassLoader叫应用类加载器,就是用来加载我们开发的类,类加载器的加载机制还涉及到一个叫双亲委派机制。这个我也不是很懂,就无法展开了。

8. AbstractBeanDefinitionReader.loadBeanDefinitions(Resource... resources)源码阅读

这个方法的源码并不复杂,主要是对这个入参resources的遍历。源码如下:

public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
	//断言空校验
	Assert.notNull(resources, "Resource array must not be null");
	int count = 0;
	Resource[] var3 = resources;
	int var4 = resources.length;

	for(int var5 = 0; var5 < var4; ++var5) {
		Resource resource = var3[var5];
		//从方法上下文推断,bean信息在这个方法中加载
		count += this.loadBeanDefinitions((Resource)resource);
	}
	return count;
}

所以继续阅读this.loadBeanDefinitions((Resource)resource)的源码逻辑。

9. XmlBeanDefinitionReader.loadBeanDefinitions(Resource resource)源码阅读

该方法中也是一个方法调用,源码如下:

public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
	return this.loadBeanDefinitions(new EncodedResource(resource));
}

这个逻辑不解释,我们继续阅读调用的方法loadBeanDefinitions(EncodedResource encodedResource)对应的源码。源码如下:

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
	Assert.notNull(encodedResource, "EncodedResource must not be null");
	if (this.logger.isTraceEnabled()) {
		this.logger.trace("Loading XML bean definitions from " + encodedResource);
	}

	Set<EncodedResource> currentResources = (Set)this.resourcesCurrentlyBeingLoaded.get();
	if (!currentResources.add(encodedResource)) {
		throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");
	} else {
		int var6;
		try {
			InputStream inputStream = encodedResource.getResource().getInputStream();
			Throwable var4 = null;

			try {
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				//该方法中加载了bean信息,即创建了bean对应的beanDefinition对象
				var6 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			} catch (Throwable var24) {
				var4 = var24;
				throw var24;
			} finally {
				if (inputStream != null) {
					if (var4 != null) {
						try {
							inputStream.close();
						} catch (Throwable var23) {
							var4.addSuppressed(var23);
						}
					} else {
						inputStream.close();
					}
				}

			}
		} catch (IOException var26) {
			throw new BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), var26);
		} finally {
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}

		}

		return var6;
	}
}

该方法的执行效果如下:

所以还得继续阅读doLoadBeanDefinitions(InputSource inputSource, Resource resource)的源码。但是从方法的命名规律来看,这是一个do开头的方法doXXX。按spring的规律,这里面才是真正干活的逻辑了。继续跟踪源码逻辑。

10. XmlBeanDefinitionReader.doLoadBeanDefinitions(InputSource inputSource, Resource resource)源码阅读

这个方法代码挺多,但是实际上需要关注的业务代码只有两行,源码如下:

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
	try {
		//创建一个文档对象Document
		Document doc = this.doLoadDocument(inputSource, resource);
		//该方法执行后,bean信息就被加载了
		int count = this.registerBeanDefinitions(doc, resource);
		if (this.logger.isDebugEnabled()) {
			this.logger.debug("Loaded " + count + " bean definitions from " + resource);
		}

		return count;
	} catch (BeanDefinitionStoreException var5) {
		throw var5;
	} catch (SAXParseException var6) {
		throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + var6.getLineNumber() + " in XML document from " + resource + " is invalid", var6);
	} catch (SAXException var7) {
		throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", var7);
	} catch (ParserConfigurationException var8) {
		throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, var8);
	} catch (IOException var9) {
		throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, var9);
	} catch (Throwable var10) {
		throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, var10);
	}
}

源码并不需要啥解释,比较简单,执行效果如下:

 我们继续关注registerBeanDefinitions(Document doc, Resource resource)的相关源码。

11. XmlBeanDefinitionReader.registerBeanDefinitions(Document doc, Resource resource)源码阅读

源码逻辑并不多,逻辑也不难,源码如下:

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
	BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();
	int countBefore = this.getRegistry().getBeanDefinitionCount();
	//该方法执行完后,beanDefinition就加载了
	documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));
	return this.getRegistry().getBeanDefinitionCount() - countBefore;
}

执行效果如下:

 所以我们还得继续往下跟踪源码。

12. DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root)源码阅读

方法doRegisterBeanDefinitions(Element root)是registerBeanDefinitions(Document doc, Resource resource)中进入的,源码如下:

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
	this.readerContext = readerContext;
	//进入DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root)
	this.doRegisterBeanDefinitions(doc.getDocumentElement());
}

我们跟着代码,阅读DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root)的相关源码,源码如下:

/**
* 解析XML文件
*
*/
protected void doRegisterBeanDefinitions(Element root) {
	BeanDefinitionParserDelegate parent = this.delegate;
	this.delegate = this.createDelegate(this.getReaderContext(), root, parent);
	if (this.delegate.isDefaultNamespace(root)) {
		String profileSpec = root.getAttribute("profile");
		if (StringUtils.hasText(profileSpec)) {
			String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; ");
			if (!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
				if (this.logger.isDebugEnabled()) {
					this.logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + this.getReaderContext().getResource());
				}

				return;
			}
		}
	}
	//该方法是一个空实现,可用于扩展
	this.preProcessXml(root);
	//方法执行后,bean信息加载了
	this.parseBeanDefinitions(root, this.delegate);
	//该方法是一个空实现,可用于扩展
	this.postProcessXml(root);
	this.delegate = parent;
}

从源码理解得知,我们还得继续阅读DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)相关的源码,但感觉距离我们想要的逻辑越来越近了。

13. DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)源码阅读

实际上并没有很复杂的逻辑,就是校验和遍历,源码如下:

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)) {
					//该代码执行后,bean信息就加载了
					this.parseDefaultElement(ele, delegate);
				} else {
					delegate.parseCustomElement(ele);
				}
			}
		}
	} else {
		delegate.parseCustomElement(root);
	}
}

执行效果如下:

 

 我们继续阅读parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)的源码

14. parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)源码阅读

该方法中,用于对标签类型的校验,我们在配置文件中,通过bean标签来描述或定义一个类,源码如下:

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
	if (delegate.nodeNameEquals(ele, "import")) {
		this.importBeanDefinitionResource(ele);
	} else if (delegate.nodeNameEquals(ele, "alias")) {
		this.processAliasRegistration(ele);
	} else if (delegate.nodeNameEquals(ele, "bean")) {
		//定义的bean会进入该逻辑进行beanDefinition的加载
		this.processBeanDefinition(ele, delegate);
	} else if (delegate.nodeNameEquals(ele, "beans")) {
		this.doRegisterBeanDefinitions(ele);
	}
}

我们继续跟踪this.processBeanDefinition(ele, delegate)的逻辑

15. processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)源码阅读

跟了这么久的源码,值得欣慰的是,就快看到结果了,坚持继续,该方法源码如下:

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
	//创建BeanDefinitionHolder对象,该对象中有个BeanDefinition对象属性,在创建BeanDefinitionHolder对象的过程中进行BeanDefinition的创建
	BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
	if (bdHolder != null) {
		bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);

		try {
			//加载bean信息的方法
			BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
		} catch (BeanDefinitionStoreException var5) {
			this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
		}
		this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
	}
}

执行效果如下:

这里面有个比较重要的方法需要展开,就是BeanDefinitionHolder的创建过程,这个不展开的话,后面源码中获取beanName的时候就会蒙蔽,我都没看到赋值,怎么一下就可以取值了呢?所以我们这里展开delegate.parseBeanDefinitionElement(ele)的源码逻辑,源码如下:

15.1 parseBeanDefinitionElement(Element ele)方法

该方法只是一个简单的调用,源码如下:

@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
	return this.parseBeanDefinitionElement(ele, (BeanDefinition)null);
}

 我们继续看this.parseBeanDefinitionElement(ele, (BeanDefinition)null)对应的逻辑,源码如下:

@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
	//获取bean标签中的id属性的值
	String id = ele.getAttribute("id");
	//获取bean标签中的name属性的值,值为""
	String nameAttr = ele.getAttribute("name");
	List<String> aliases = new ArrayList();
	if (StringUtils.hasLength(nameAttr)) {
		String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
		aliases.addAll(Arrays.asList(nameArr));
	}
	//将获取的bean标签中的id属性的值赋值为beanName
	String beanName = id;
	if (!StringUtils.hasText(id) && !aliases.isEmpty()) {
		beanName = (String)aliases.remove(0);
		if (this.logger.isTraceEnabled()) {
			this.logger.trace("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases");
		}
	}
	//方法调用的地方可知,BeanDefinition传的是null
	if (containingBean == null) { //为true
		this.checkNameUniqueness(beanName, aliases, ele);
	}
	//创建BeanDefinition对象
	AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean);
	if (beanDefinition != null) {
		if (!StringUtils.hasText(beanName)) {
			try {
				if (containingBean != null) {
					beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
				} else {
					beanName = this.readerContext.generateBeanName(beanDefinition);
					String beanClassName = beanDefinition.getBeanClassName();
					if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
						aliases.add(beanClassName);
					}
				}

				if (this.logger.isTraceEnabled()) {
					this.logger.trace("Neither XML 'id' nor 'name' specified - using generated bean name [" + beanName + "]");
				}
			} catch (Exception var9) {
				this.error(var9.getMessage(), ele);
				return null;
			}
		}

		String[] aliasesArray = StringUtils.toStringArray(aliases);
		//创建BeanDefinitionHolder对象时,将BeanDefinition,beanName赋值,所以后面才可以取到beanName的值
		return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
	} else {
		return null;
	}
}

然后我们继续看创建BeanDefinition的源码。AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean);跟踪parseBeanDefinitionElement(ele, beanName, containingBean)的源码逻辑,逻辑如下:

@Nullable
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean) {
	this.parseState.push(new BeanEntry(beanName));
	//保存类的全限定名,com.xxx.xxx.xxx.User
	String className = null;
	if (ele.hasAttribute("class")) {
		className = ele.getAttribute("class").trim();
	}

	String parent = null;
	if (ele.hasAttribute("parent")) {
		parent = ele.getAttribute("parent");
	}

	try {
		//创建GenericBeanDefinition对象,并根据clas获取Clazz对象
		AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);
		/**默认值的设置 start*/
		this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
		bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));
		this.parseMetaElements(ele, bd);
		this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
		this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
		this.parseConstructorArgElements(ele, bd);
		this.parsePropertyElements(ele, bd);
		this.parseQualifierElements(ele, bd);
		bd.setResource(this.readerContext.getResource());
		bd.setSource(this.extractSource(ele));
		/**默认值的设置  end*/
		AbstractBeanDefinition var7 = bd;
		return var7;
	} catch (ClassNotFoundException var13) {
		this.error("Bean class [" + className + "] not found", ele, var13);
	} catch (NoClassDefFoundError var14) {
		this.error("Class that bean class [" + className + "] depends on not found", ele, var14);
	} catch (Throwable var15) {
		this.error("Unexpected failure during bean definition parsing", ele, var15);
	} finally {
		this.parseState.pop();
	}

	return null;
}

然后我们还得关注createBeanDefinition(@Nullable String className, @Nullable String parentName)对应的源码,源码中调用createBeanDefinition(@Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader)方法,两个方法的源码如下:

  • createBeanDefinition(@Nullable String className, @Nullable String parentName)
protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName) throws ClassNotFoundException {
	return BeanDefinitionReaderUtils.createBeanDefinition(parentName, className, this.readerContext.getBeanClassLoader());
}
  • createBeanDefinition(@Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader)
public static AbstractBeanDefinition createBeanDefinition(@Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {
	GenericBeanDefinition bd = new GenericBeanDefinition();
	bd.setParentName(parentName);
	if (className != null) {
		if (classLoader != null) {
			//得到字节码Clazz对象
			bd.setBeanClass(ClassUtils.forName(className, classLoader));
		} else {
			bd.setBeanClassName(className);
		}
	}

	return bd;
}

16. BeanDefinitionReaderUtils.registerBeanDefinition()源码阅读

到了这里其实可以认为具体逻辑肯定是在这里处理了,因为在之前的Bean创建流程中,他是通过一个BeanUtils工具类创建,同理推测,这个是最终的方法,其源码如下:

public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
	//获取并的名称
	String beanName = definitionHolder.getBeanName();
	//注册beanDefinition信息
	registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
	//这个没有数据,逻辑不会进入
    String[] aliases = definitionHolder.getAliases();
	if (aliases != null) {
		String[] var4 = aliases;
		int var5 = aliases.length;

		for(int var6 = 0; var6 < var5; ++var6) {
			String alias = var4[var6];
			registry.registerAlias(beanName, alias);
		}
	}
}

然后我们继续阅读registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition())对应的源码,源码如下:

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
	Assert.hasText(beanName, "Bean name must not be empty");
	Assert.notNull(beanDefinition, "BeanDefinition must not be null");
	if (beanDefinition instanceof AbstractBeanDefinition) {
		try {
			((AbstractBeanDefinition)beanDefinition).validate();
		} catch (BeanDefinitionValidationException var8) {
			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var8);
		}
	}
	//从beanDefinitionMap获取beanName,beanDefinitionMap是一个有beanName作为Key,BeanDefinition作为value的Map。
	BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
	if (existingDefinition != null) {
		if (!this.isAllowBeanDefinitionOverriding()) {
			throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
		}

		if (existingDefinition.getRole() < beanDefinition.getRole()) {
			if (this.logger.isInfoEnabled()) {
				this.logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
			}
		} else if (!beanDefinition.equals(existingDefinition)) {
			if (this.logger.isDebugEnabled()) {
				this.logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
			}
		} else if (this.logger.isTraceEnabled()) {
			this.logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
		}

		this.beanDefinitionMap.put(beanName, beanDefinition);
	} else {
		//判断Bean工厂是否已经开始创建Bean了
		if (this.hasBeanCreationStarted()) {
			synchronized(this.beanDefinitionMap) {
				this.beanDefinitionMap.put(beanName, beanDefinition);
				List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
				updatedDefinitions.addAll(this.beanDefinitionNames);
				updatedDefinitions.add(beanName);
				this.beanDefinitionNames = updatedDefinitions;
				this.removeManualSingletonName(beanName);
			}
		} else {
			//将beanDefinition保存至beanDefinitionMap的Map集合中
			this.beanDefinitionMap.put(beanName, beanDefinition);
			//将beanDefinition保存至beanDefinitionNames的List集合中
			this.beanDefinitionNames.add(beanName);
			//疑问点?
			this.removeManualSingletonName(beanName);
		}

		this.frozenBeanDefinitionNames = null;
	}

	if (existingDefinition == null && !this.containsSingleton(beanName)) {
		if (this.isConfigurationFrozen()) {
			this.clearByTypeCache();
		}
	} else {
		this.resetBeanDefinition(beanName);
	}
}

到这里,一个bean的beanDefinition的信息的获取流程,也可以理解为BeanDefinition的探索就结束了,最后的接口中的this.removeManualSingletonName(beanName)方法目前还没理解,有大神知道的,可以告知一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值