Spring框架进阶(六)Spring V3.0 IOC源码分析流程

目录

1、总体分析

2、XML配置源码阅读

2.1、XML配置

2.1.1 寻找入口

2.1.2、获取配置文件路径

2.1.3、开始启动

2.1.4、创建容器

2.1.5、载入配置路径

2.1.6、读取配置内容

2.1.7、分配解析策略

2.1.8、分配注册策略

2.1.9、向容器注册

2.2、XML方式总结

2.2.1、保存配置文件路径

2.2.2、定位配置文件

2.2.3、加载配置文件信息

2.2.4、注册BeanDefinition至Map

3、注解方式阅读源码

3.1、起始入口

3.2、类参数构造执行

3.2.1、作用域解析

3.2.2、通用注解处理

3.2.3、代理模式选择

3.2.4、注册BeanDefinition

3.3、路径构造执行

3.4、web版本


1、总体分析

对于IOC的加载流程,可以在之前的IOC源码模仿中窥见一二。

总体步骤可以分为:

第一步,在ApplicationContext中,BeandefinitionReader用loadBeanDefinitions方法读取到配置文件的配置,保存到BeanDefinition之中,完成定位。

第二步,在ApplicationContext中获取到Beandefinition的列表,Beandefinition包含有Bean的名称和类信息,完成加载。

第三步,DefaultListableBeanFactory用doRegistryBeanDefinition方法将Beandefinition的列表放入BeanDefinitionMap中,完成注册

2、XML配置源码阅读

ApplicationContext是通常意义上的初始入口,从init方法内,直接调用ApplicationContext类,但实际上,因为配置方式的不同,所使用的ApplicationContext子类也并不相同。

2.1、XML配置

详细步骤可以分解为:

  1. 寻找入口
  2. 获取配置文件路径
  3. 开始启动
  4. 创建容器
  5. 载入配置路径
  6. 开始读取配置文件
  7. 分配解析策略
  8. 分配注册策略
  9. 向容器注册

2.1.1 寻找入口

ClassPathXmlApplicationContext是XML类型配置的子类,从构造中可以看到,它先是调用了父类的方法,然后setConfigLocations(configLocations)方法获取到了配置信息的地址,最后执行refresh()方法。

public ClassPathXmlApplicationContext(
		String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
		throws BeansException {

	super(parent);
	setConfigLocations(configLocations);
	if (refresh) {
		refresh();
	}
}

2.1.2、获取配置文件路径

AbstractRefreshableConfigApplicationContext是setConfigLocations(configLocations)方法的来源,在这个方法里,将获取到的所有的配置地址都存方在一个String数组之中。

public void setConfigLocations(@Nullable String... locations) {
	if (locations != null) {
		Assert.noNullElements(locations, "Config locations must not be null");
		this.configLocations = new String[locations.length];
		for (int i = 0; i < locations.length; i++) {
			// resolvePath为同一个类中将字符串解析为路径的方法
			this.configLocations[i] = resolvePath(locations[i]).trim();
		}
	}
	else {
		this.configLocations = null;
	}
}

2.1.3、开始启动

AbstractApplicationContext之中包含了对应的refresh()方法,在这个方法内,可以看到第一个方法是准备刷新prepareRefresh(),第二个方法ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()是做什么的呢?

这里有一个熟悉的东西,ConfigurableListableBeanFactory,这个一定与DefaultListableBeanFactory有关,从方法名中猜测到,这个是要获取到刷新BeanFactory的一个方法,很显然,这个是为了得到一个BeanFactory,但具体是做什么的,还需要继续探究。

总体来说,refresh()方法主要负责整个IOC容器的刷新,包括构建和载入Bean的配置信息。如果IOC容器已经存在,就要被销毁,重新创建,是一个重启的过程。

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// Prepare this context for refreshing.
		//1、调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
		prepareRefresh();

		// Tell the subclass to refresh the internal bean factory.
		//2、告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从
		//子类的refreshBeanFactory()方法启动
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// Prepare the bean factory for use in this context.
		//3、为BeanFactory配置容器特性,例如类加载器、事件处理器等
		prepareBeanFactory(beanFactory);

		try {
			// Allows post-processing of the bean factory in context subclasses.
			//4、为容器的某些子类指定特殊的BeanPost事件处理器
			postProcessBeanFactory(beanFactory);

			// Invoke factory processors registered as beans in the context.
			//5、调用所有注册的BeanFactoryPostProcessor的Bean
			invokeBeanFactoryPostProcessors(beanFactory);

			// Register bean processors that intercept bean creation.
			//6、为BeanFactory注册BeanPost事件处理器.
			//BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件
			registerBeanPostProcessors(beanFactory);

			// Initialize message source for this context.
			//7、初始化信息源,和国际化相关.
			initMessageSource();

			// Initialize event multicaster for this context.
			//8、初始化容器事件传播器.
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses.
			//9、调用子类的某些特殊Bean初始化方法
			onRefresh();

			// Check for listener beans and register them.
			//10、为事件传播器注册事件监听器.
			registerListeners();

			// Instantiate all remaining (non-lazy-init) singletons.
			//11、初始化所有剩余的单例Bean
			finishBeanFactoryInitialization(beanFactory);

			// Last step: publish corresponding event.
			//12、初始化容器的生命周期事件处理器,并发布容器的生命周期事件
			finishRefresh();
		}

		catch (BeansException ex) {
			if (logger.isWarnEnabled()) {
				logger.warn("Exception encountered during context initialization - " +
						"cancelling refresh attempt: " + ex);
			}

			// Destroy already created singletons to avoid dangling resources.
			//13、销毁已创建的Bean
			destroyBeans();

			// Reset 'active' flag.
			//14、取消refresh操作,重置容器的同步标识。
			cancelRefresh(ex);

			// Propagate exception to caller.
			throw ex;
		}

		finally {
			// Reset common introspection caches in Spring's core, since we
			// might not ever need metadata for singleton beans anymore...
			//15、重设公共缓存
			resetCommonCaches();
		}
	}
}

2.1.4、创建容器

依然是AbstractApplicationContext之中的方法,第一个方法refreshBeanFactory(),刷新BeanFactory,第二个方法没什么好说的,就是将beanFactory拿到并返回,关键是第一个方法。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
	//这里使用了委派设计模式,父类定义了抽象的refreshBeanFactory()方法,具体实现调用子类容器的refreshBeanFactory()方法
	refreshBeanFactory();
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	if (logger.isDebugEnabled()) {
		logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
	}
	return beanFactory;
}

AbstractRefreshableApplicationContext,不同于之前的AbstractRefreshableConfigApplicationContext用来获取到配置文件的地址,AbstractRefreshableApplicationContext主要用来实现刷新功能,其为AbstractApplicationContext类的子类,使用委派模式,将refreshBeanFactory()方法的实现写在子类之中

refreshBeanFactory()方法的实现并不复杂,如果存在容器,就销毁Bean,并且关闭容器,然后开始创建。

创建自然是最重要的,因为我们看到了一个熟悉的东西,DefaultListableBeanFactory beanFactory = createBeanFactory(),这个我们太熟了,再看下面的方法,loadBeanDefinitions(beanFactory),这个也太熟悉了先创建DefaultListableBeanFactor,再用loadBeanDefinitions(beanFactory)方法,获取到BeanDefinitionsList。

protected final void refreshBeanFactory() throws BeansException {
	//如果已经有容器,销毁容器中的bean,关闭容器
	if (hasBeanFactory()) {
		destroyBeans();
		closeBeanFactory();
	}
	try {
		//创建IOC容器
		DefaultListableBeanFactory beanFactory = createBeanFactory();
		beanFactory.setSerializationId(getId());
		//对IOC容器进行定制化,如设置启动参数,开启注解的自动装配等
		customizeBeanFactory(beanFactory);
		//调用载入Bean定义的方法,主要这里又使用了一个委派模式,在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器
		loadBeanDefinitions(beanFactory);
		synchronized (this.beanFactoryMonitor) {
			this.beanFactory = beanFactory;
		}
	}
	catch (IOException ex) {
		throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
	}
}

2.1.5、载入配置路径

AbstractXmlApplicationContext,依然是一个抽象类,是上一个AbstractRefreshableConfigApplicationContext的子类,是的这里再次使用委派模式,实现loadBeanDefinitions(beanFactory)方法

第一行,看到了一个很熟悉的东西,BeanDefinitionReader,配置文件读取,获取到对应的Reader之后,继续向下看,期间放入了各种配置,最后执行方法loadBeanDefinitions(beanDefinitionReader),显然这里才继续执行读取了

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
	// Create a new XmlBeanDefinitionReader for the given BeanFactory.
	//创建XmlBeanDefinitionReader,即创建Bean读取器,并通过回调设置到容器中去,容  器使用该读取器读取Bean定义资源
	XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

	// Configure the bean definition reader with this context's
	// resource loading environment.
	//为Bean读取器设置Spring资源加载器,AbstractXmlApplicationContext的
	//祖先父类AbstractApplicationContext继承DefaultResourceLoader,因此,容器本身也是一个资源加载器
	beanDefinitionReader.setEnvironment(this.getEnvironment());
	beanDefinitionReader.setResourceLoader(this);
	//为Bean读取器设置SAX xml解析器
	beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

	// Allow a subclass to provide custom initialization of the reader,
	// then proceed with actually loading the bean definitions.
	//当Bean读取器读取Bean定义的Xml资源文件时,启用Xml的校验机制
	initBeanDefinitionReader(beanDefinitionReader);
	//Bean读取器真正实现加载的方法
	loadBeanDefinitions(beanDefinitionReader);
}

依然是AbstractXmlApplicationContext类,将Reader读取到之后,获取资源,如果资源不为空,就执行Reader的loadBeanDefinitions(configResources)方法,可以看到,这里根据获取到的资源类型分为两个方法,一个以resource为参,一个以string为参

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
	//获取Bean定义资源的定位
	Resource[] configResources = getConfigResources();
	if (configResources != null) {
		//Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位
		//的Bean定义资源
		reader.loadBeanDefinitions(configResources);
	}
	//如果子类中获取的Bean定义资源定位为空,则获取FileSystemXmlApplicationContext构造方法中setConfigLocations方法设置的资源
	String[] configLocations = getConfigLocations();
	if (configLocations != null) {
		//Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位
		//的Bean定义资源
		reader.loadBeanDefinitions(configLocations);
	}
}

AbstractBeanDefinitionReader类为XmlBeanDefinitionReader的父类,可以先看loadBeanDefinitions(String location)方法,这里是loadBeanDefinitions(String location, null)的重载方法,继续向下,可以看到重载方法中还有loadBeanDefinitions(resources)方法

@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
	return loadBeanDefinitions(location, null);
}

public int loadBeanDefinitions(String location, @Nullable Set actualResources) throws BeanDefinitionStoreException {
	//获取在IoC容器初始化过程中设置的资源加载器
	ResourceLoader resourceLoader = getResourceLoader();
	if (resourceLoader == null) {
		throw new BeanDefinitionStoreException(
				"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
	}

	if (resourceLoader instanceof ResourcePatternResolver) {
		// Resource pattern matching available.
		try {
			//将指定位置的Bean定义资源文件解析为Spring IOC容器封装的资源
			//加载多个指定位置的Bean定义资源文件
			Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
			//委派调用其子类XmlBeanDefinitionReader的方法,实现加载功能
			int loadCount = loadBeanDefinitions(resources);
			if (actualResources != null) {
				for (Resource resource : resources) {
					actualResources.add(resource);
				}
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
			}
			return loadCount;
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"Could not resolve bean definition resource pattern [" + location + "]", ex);
		}
	}
	else {
		// Can only load single resources by absolute URL.
		//将指定位置的Bean定义资源文件解析为Spring IOC容器封装的资源
		//加载单个指定位置的Bean定义资源文件
		Resource resource = resourceLoader.getResource(location);
		//委派调用其子类XmlBeanDefinitionReader的方法,实现加载功能
		int loadCount = loadBeanDefinitions(resource);
		if (actualResources != null) {
			actualResources.add(resource);
		}
		if (logger.isDebugEnabled()) {
			logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
		}
		return loadCount;
	}
}

2.1.6、读取配置内容

这个方法是子类XmlBeanDefinitionReader的方法,依旧调用此类中的loadBeanDefinitions方法,最后可以看到doLoadBeanDefinitions方法,在源码中,带有do开头的方法就是真正的执行方法。

public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
	//将读入的XML资源进行特殊编码处理
	return loadBeanDefinitions(new EncodedResource(resource));
}

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
	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的IO流
		InputStream inputStream = encodedResource.getResource().getInputStream();
		try {
			//从InputStream中得到XML的解析源
			InputSource inputSource = new InputSource(inputStream);
			if (encodedResource.getEncoding() != null) {
				inputSource.setEncoding(encodedResource.getEncoding());
			}
			//这里是具体的读取过程
			return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
		}
		finally {
			//关闭从Resource中得到的IO流
			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();
		}
	}
}

那么回去重新看以resource为参的方法

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
	//获取Bean定义资源的定位
	Resource[] configResources = getConfigResources();
	if (configResources != null) {
		//Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位
		//的Bean定义资源
		reader.loadBeanDefinitions(configResources);
	}
	//如果子类中获取的Bean定义资源定位为空,则获取FileSystemXmlApplicationContext构造方法中setConfigLocations方法设置的资源
	String[] configLocations = getConfigLocations();
	if (configLocations != null) {
		//Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位
		//的Bean定义资源
		reader.loadBeanDefinitions(configLocations);
	}
}

在这个方法中,依然有loadBeanDefinitions(resource)方法

public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
	Assert.notNull(resources, "Resource array must not be null");
	int counter = 0;
	for (Resource resource : resources) {
		counter += loadBeanDefinitions(resource);
	}
	return counter;
}

执行的依旧是XmlBeanDefinitionReader的方法,依旧调用此类中的loadBeanDefinitions方法,最后可以看到doLoadBeanDefinitions方法,由此可见,最后执行的是相同的方法。

public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
	//将读入的XML资源进行特殊编码处理
	return loadBeanDefinitions(new EncodedResource(resource));
}

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
	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的IO流
		InputStream inputStream = encodedResource.getResource().getInputStream();
		try {
			//从InputStream中得到XML的解析源
			InputSource inputSource = new InputSource(inputStream);
			if (encodedResource.getEncoding() != null) {
				inputSource.setEncoding(encodedResource.getEncoding());
			}
			//这里是具体的读取过程
			return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
		}
		finally {
			//关闭从Resource中得到的IO流
			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();
		}
	}
}

2.1.7、分配解析策略

依旧是XmlBeanDefinitionReader类中的方法,可以看到这个方法registerBeanDefinitions(doc, resource),这也是一个很熟悉的方法,执行BeanDefinition的注册行为。

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
		throws BeanDefinitionStoreException {
	try {
		//将XML文件转换为DOM对象,解析过程由documentLoader实现
		Document doc = doLoadDocument(inputSource, resource);
		//这里是启动对Bean定义解析的详细过程,该解析过程会用到Spring的Bean配置规则
		return registerBeanDefinitions(doc, resource);
	}
	catch (BeanDefinitionStoreException ex) {
		throw ex;
	}
	catch (SAXParseException ex) {
		throw new XmlBeanDefinitionStoreException(resource.getDescription(),
				"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
	}
	catch (SAXException ex) {
		throw new XmlBeanDefinitionStoreException(resource.getDescription(),
				"XML document from " + resource + " is invalid", ex);
	}
	catch (ParserConfigurationException ex) {
		throw new BeanDefinitionStoreException(resource.getDescription(),
				"Parser configuration exception parsing XML from " + resource, ex);
	}
	catch (IOException ex) {
		throw new BeanDefinitionStoreException(resource.getDescription(),
				"IOException parsing XML document from " + resource, ex);
	}
	catch (Throwable ex) {
		throw new BeanDefinitionStoreException(resource.getDescription(),
				"Unexpected exception parsing XML document from " + resource, ex);
	}
}

XmlBeanDefinitionReader类的registerBeanDefinitions方法继续进行BeanDefinitions的注册,在这个过程中,进入到DefaultBeanDefinitionDocumentReader类的registerBeanDefinitions之中

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
	//得到BeanDefinitionDocumentReader来对xml格式的BeanDefinition解析
	BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
	//获得容器中注册的Bean数量
	int countBefore = getRegistry().getBeanDefinitionCount();
	//解析过程入口,这里使用了委派模式,BeanDefinitionDocumentReader只是个接口,
	//具体的解析实现过程有实现类DefaultBeanDefinitionDocumentReader完成
	documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
	//统计解析的Bean数量
	return getRegistry().getBeanDefinitionCount() - countBefore;
}

DefaultBeanDefinitionDocumentReader类包含有doRegisterBeanDefinitions(root)方法,这个是真正执行注册的方法

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
	//获得XML描述符
	this.readerContext = readerContext;
	logger.debug("Loading bean definitions");
	//获得Document的根元素
	Element root = doc.getDocumentElement();
	doRegisterBeanDefinitions(root);
}

DefaultBeanDefinitionDocumentReader类包含有BeanDefinitionParserDelegate parent = this.delegate,这依旧是一个委派方法,用来执行对应的解析,那么跟着这个委派的类,继续向下找,找到parseBeanDefinitions(root, this.delegate)方法,这个方法就是继续执行的方法

protected void doRegisterBeanDefinitions(Element root) {
	// Any nested  elements will cause recursion in this method. In
	// order to propagate and preserve  default-* attributes correctly,
	// keep track of the current (parent) delegate, which may be null. Create
	// the new (child) delegate with a reference to the parent for fallback purposes,
	// then ultimately reset this.delegate back to its original (parent) reference.
	// this behavior emulates a stack of delegates without actually necessitating one.

	//具体的解析过程由BeanDefinitionParserDelegate实现,
	//BeanDefinitionParserDelegate中定义了Spring Bean定义XML文件的各种元素
	BeanDefinitionParserDelegate parent = this.delegate;
	this.delegate = createDelegate(getReaderContext(), root, parent);

	if (this.delegate.isDefaultNamespace(root)) {
		String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
		if (StringUtils.hasText(profileSpec)) {
			String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
					profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
				if (logger.isInfoEnabled()) {
					logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
							"] not matching: " + getReaderContext().getResource());
				}
				return;
			}
		}
	}

	//在解析Bean定义之前,进行自定义的解析,增强解析过程的可扩展性
	preProcessXml(root);
	//从Document的根元素开始进行Bean定义的Document对象
	parseBeanDefinitions(root, this.delegate);
	//在解析Bean定义之后,进行自定义的解析,增加解析过程的可扩展性
	postProcessXml(root);

	this.delegate = parent;
}

DefaultBeanDefinitionDocumentReader类的parseDefaultElement(ele, delegate)方法解析Bean标签,继续向下

//使用Spring的Bean规则从Document的根元素开始进行Bean定义的Document对象
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
	//Bean定义的Document对象使用了Spring默认的XML命名空间
	if (delegate.isDefaultNamespace(root)) {
		//获取Bean定义的Document对象根元素的所有子节点
		NodeList nl = root.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			//获得Document节点是XML元素节点
			if (node instanceof Element) {
				Element ele = (Element) node;
				//Bean定义的Document的元素节点使用的是Spring默认的XML命名空间
				if (delegate.isDefaultNamespace(ele)) {
					//使用Spring的Bean规则解析元素节点
					parseDefaultElement(ele, delegate);
				}
				else {
					//没有使用Spring默认的XML命名空间,则使用用户自定义的解//析规则解析元素节点
					delegate.parseCustomElement(ele);
				}
			}
		}
	}
	else {
		//Document的根节点没有使用Spring默认的命名空间,则使用用户自定义的
		//解析规则解析Document根节点
		delegate.parseCustomElement(root);
	}
}

DefaultBeanDefinitionDocumentReader类的processBeanDefinition(ele, delegate),继续解析Bean标签,继续向下

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
	//如果元素节点是导入元素,进行导入解析
	if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
		importBeanDefinitionResource(ele);
	}
	//如果元素节点是别名元素,进行别名解析
	else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
		processAliasRegistration(ele);
	}
	//元素节点既不是导入元素,也不是别名元素,即普通的元素,
	//按照Spring的Bean规则解析元素
	else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
		processBeanDefinition(ele, delegate);
	}
	else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
		// recurse
		doRegisterBeanDefinitions(ele);
	}
}

DefaultBeanDefinitionDocumentReader类的BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())方法,调用BeanDefinitionReaderUtils工具类去注册BeanDefinitions。

除此之外,第一行代码BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele)也相当重要,这个方法展示了在BeanDefinition是如何封装的。

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
	BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
	// BeanDefinitionHolder是对BeanDefinition的封装,即Bean定义的封装类
	//对Document对象中元素的解析由BeanDefinitionParserDelegate实现
	// BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
	if (bdHolder != null) {
		bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
		try {
			// Register the final decorated instance.
			//向Spring IOC容器注册解析得到的Bean定义,这是Bean定义向IOC容器注册的入口
			BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
		}
		catch (BeanDefinitionStoreException ex) {
			getReaderContext().error("Failed to register bean definition with name '" +
					bdHolder.getBeanName() + "'", ele, ex);
		}
		// Send registration event.
		//在完成向Spring IOC容器注册解析得到的Bean定义之后,发送注册事件
		getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
	}
}

 BeanDefinitionParserDelegate类中的方法parseBeanDefinitionElement内的AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean)继续对BeanDefinition进行构建,

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
	return parseBeanDefinitionElement(ele, null);
}

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
	//获取元素中的id属性值
	String id = ele.getAttribute(ID_ATTRIBUTE);
	//获取元素中的name属性值
	String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

	//获取元素中的alias属性值
	List aliases = new ArrayList<>();

	//将元素中的所有name属性值存放到别名中
	if (StringUtils.hasLength(nameAttr)) {
		String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
		aliases.addAll(Arrays.asList(nameArr));
	}

	String beanName = id;
	//如果元素中没有配置id属性时,将别名中的第一个值赋值给beanName
	if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
		beanName = aliases.remove(0);
		if (logger.isDebugEnabled()) {
			logger.debug("No XML 'id' specified - using '" + beanName +
					"' as bean name and " + aliases + " as aliases");
		}
	}

	//检查元素所配置的id或者name的唯一性,containingBean标识
	//元素中是否包含子元素
	if (containingBean == null) {
		//检查元素所配置的id、name或者别名是否重复
		checkNameUniqueness(beanName, aliases, ele);
	}

	//详细对元素中配置的Bean定义进行解析的地方
	AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
	if (beanDefinition != null) {
		if (!StringUtils.hasText(beanName)) {
			try {
				if (containingBean != null) {
					//如果元素中没有配置id、别名或者name,且没有包含子元素
					//元素,为解析的Bean生成一个唯一beanName并注册
					beanName = BeanDefinitionReaderUtils.generateBeanName(
							beanDefinition, this.readerContext.getRegistry(), true);
				}
				else {
					//如果元素中没有配置id、别名或者name,且包含了子元素
					//元素,为解析的Bean使用别名向IOC容器注册
					beanName = this.readerContext.generateBeanName(beanDefinition);
					// Register an alias for the plain bean class name, if still possible,
					// if the generator returned the class name plus a suffix.
					// This is expected for Spring 1.2/2.0 backwards compatibility.
					//为解析的Bean使用别名注册时,为了向后兼容
					//Spring1.2/2.0,给别名添加类名后缀
					String beanClassName = beanDefinition.getBeanClassName();
					if (beanClassName != null &&
							beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
							!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
						aliases.add(beanClassName);
					}
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Neither XML 'id' nor 'name' specified - " +
							"using generated bean name [" + beanName + "]");
				}
			}
			catch (Exception ex) {
				error(ex.getMessage(), ele);
				return null;
			}
		}
		String[] aliasesArray = StringUtils.toStringArray(aliases);
		return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
	}
	//当解析出错时,返回null
	return null;
}

  BeanDefinitionParserDelegate类中的方法parseBeanDefinitionElement保存了BeanDefinition中需要的一些属性和内容,大致完成了构建。

public AbstractBeanDefinition parseBeanDefinitionElement(
		Element ele, String beanName, @Nullable BeanDefinition containingBean) {
	//记录解析的
	this.parseState.push(new BeanEntry(beanName));

	//这里只读取元素中配置的class名字,然后载入到BeanDefinition中去
	//只是记录配置的class名字,不做实例化,对象的实例化在依赖注入时完成
	String className = null;

	//如果元素中配置了parent属性,则获取parent属性的值
	if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
		className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
	}
	String parent = null;
	if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
		parent = ele.getAttribute(PARENT_ATTRIBUTE);
	}

	try {
		//根据元素配置的class名称和parent属性值创建BeanDefinition
		//为载入Bean定义信息做准备
		AbstractBeanDefinition bd = createBeanDefinition(className, parent);

		//对当前的元素中配置的一些属性进行解析和设置,如配置的单态(singleton)属性等
		parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
		//为元素解析的Bean设置description信息
		bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

		//对元素的meta(元信息)属性解析
		parseMetaElements(ele, bd);
		//对元素的lookup-method属性解析
		parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
		//对元素的replaced-method属性解析
		parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

		//解析元素的构造方法设置
		parseConstructorArgElements(ele, bd);
		//解析元素的设置
		parsePropertyElements(ele, bd);
		//解析元素的qualifier属性
		parseQualifierElements(ele, bd);

		//为当前解析的Bean设置所需的资源和依赖对象
		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();
	}

	//解析元素出错时,返回null
	return null;
}

2.1.8、分配注册策略

BeanDefinitionReaderUtils工具类中,执行registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition())方法

public static void registerBeanDefinition(
		BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
		throws BeanDefinitionStoreException {

	// Register bean definition under primary name.
	//获取解析的BeanDefinition的名称
	String beanName = definitionHolder.getBeanName();
	//向IOC容器注册BeanDefinition
	registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

	// Register aliases for bean name, if any.
	//如果解析的BeanDefinition有别名,向容器为其注册别名
	String[] aliases = definitionHolder.getAliases();
	if (aliases != null) {
		for (String alias : aliases) {
			registry.registerAlias(beanName, alias);
		}
	}
}

2.1.9、向容器注册

最后,来到DefaultListableBeanFactory类,最终这里,我们终于看到了想要看的东西:

this.beanDefinitionMap.put(beanName, beanDefinition);

这个beanDefinitionMap就是

private final Map beanDefinitionMap = new ConcurrentHashMap<>(256);

专用来保存注册信息的BeanDefinition

这显然符合最开始的IOC设计,ApplicationContext持有DefaultListableBeanFactory的引用,两者都继承了BeanFactory,是静态代理模式。

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");

	//校验解析的BeanDefiniton
	if (beanDefinition instanceof AbstractBeanDefinition) {
		try {
			((AbstractBeanDefinition) beanDefinition).validate();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
					"Validation of bean definition failed", ex);
		}
	}

	BeanDefinition oldBeanDefinition;

	oldBeanDefinition = this.beanDefinitionMap.get(beanName);

	if (oldBeanDefinition != null) {
		if (!isAllowBeanDefinitionOverriding()) {
			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 (!beanDefinition.equals(oldBeanDefinition)) {
			if (this.logger.isInfoEnabled()) {
				this.logger.info("Overriding bean definition for bean '" + beanName +
						"' with a different definition: replacing [" + oldBeanDefinition +
						"] with [" + beanDefinition + "]");
			}
		}
		else {
			if (this.logger.isDebugEnabled()) {
				this.logger.debug("Overriding bean definition for bean '" + beanName +
						"' with an equivalent definition: replacing [" + oldBeanDefinition +
						"] with [" + beanDefinition + "]");
			}
		}
		this.beanDefinitionMap.put(beanName, beanDefinition);
	}
	else {
		if (hasBeanCreationStarted()) {
			// Cannot modify startup-time collection elements anymore (for stable iteration)
			//注册的过程中需要线程同步,以保证数据的一致性
			synchronized (this.beanDefinitionMap) {
				this.beanDefinitionMap.put(beanName, beanDefinition);
				List updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
				updatedDefinitions.addAll(this.beanDefinitionNames);
				updatedDefinitions.add(beanName);
				this.beanDefinitionNames = updatedDefinitions;
				if (this.manualSingletonNames.contains(beanName)) {
					Set updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
					updatedSingletons.remove(beanName);
					this.manualSingletonNames = updatedSingletons;
				}
			}
		}
		else {
			// Still in startup registration phase
			this.beanDefinitionMap.put(beanName, beanDefinition);
			this.beanDefinitionNames.add(beanName);
			this.manualSingletonNames.remove(beanName);
		}
		this.frozenBeanDefinitionNames = null;
	}

	//检查是否有同名的BeanDefinition已经在IOC容器中注册
	if (oldBeanDefinition != null || containsSingleton(beanName)) {
		//重置所有已经注册过的BeanDefinition的缓存
		resetBeanDefinition(beanName);
	}
}

2.2、XML方式总结

以下流程总结包含类和方法,流程顺序为类中调用某一方法至另一类中

2.2.1、保存配置文件路径

ClassPathXmlApplicationContext:起始ApplicationContext,根据构造方法,执行setConfigLocations去获取文件路径并保存

setConfigLocations:保存至对应String数组

AbstractRefreshableApplicationContext:具体执行位置

2.2.2、定位配置文件

ClassPathXmlApplicationContext:起始ApplicationContext,根据构造方法,执行refresh

refresh:容器的刷新功能,如果不存在容器,就创建一个容器,如果已经存在,就注销Bean,销毁容器,重新建立

AbstractApplicationContext:ClassPathXmlApplicationContext父类

obtainFreshBeanFactory:告诉子类开始执行refreshBeanFactory方法

AbstractApplicationContext:ClassPathXmlApplicationContext父类

refreshBeanFactory:如果已有容器,销毁,创建IOC容器DefaultListableBeanDefinition,执行loadBeanDefinitions方法,开始准备读取

AbstractRefreshableApplicationContext:

loadBeanDefinitions:创建Bean读取器XmlBeanDefinitionReader,继续执行读取

2.2.3、加载配置文件信息

AbstractXmlApplicationContext:

loadBeanDefinitions:资源定位,分为两种方式,Resource参数和String参数两种

AbstractBeanDefinitionReader:

loadBeanDefinitions:两种方式最终都将到达XmlBeanDefinitionReader

XmlBeanDefinitionReader:

doLoadBeanDefinitions:真正执行读取的方法,

XmlBeanDefinitionReader:

registerBeanDefinitions:执行注册方法

2.2.4、注册BeanDefinition至Map

DefaultBeanDefinitionDocumentReader:默认BeanDefinition文档读取器,执行读取

doRegisterBeanDefinitions:执行BeanDefinition的注册流程

DefaultBeanDefinitionDocumentReader:继续执行读取

processBeanDefinition:根据委派的BeanDefinitionParserDelegate解析配置文件,装载BeanDefinition类信息并封装到BeanDefinitionHolder中

获取到封装BeanDefinition的BeanDefinitionHolder,并执行下一步的保存

BeanDefinitionReaderUtils:将解析的BeanDefinitionHold注册到容器中

registerBeanDefinition:获取到BeanDefinition用来执行最后的保存

DefaultListableBeanFactory:最终保存BeanDefinition的类,保存到beanDefinitionMap

3、注解方式阅读源码

注解方式和XML方式略有不同

3.1、起始入口

AnnotationConfigApplicationContext是注解的起始类,包含一个读取器AnnotatedBeanDefinitionReader和扫描器ClassPathBeanDefinitionScanner,在默认的无参构造中将读取器和扫描器会被初始化,并且在有参构造中都调用了无参构造。

在两个带有参数的构造器中可以看到,这是两种不同的扫描方式,一种是使用配置类,一种是使用给定包路径扫描

/保存一个读取注解的Bean定义读取器,并将其设置到容器中
private final AnnotatedBeanDefinitionReader reader;

//保存一个扫描指定类路径中注解Bean定义的扫描器,并将其设置到容器中
private final ClassPathBeanDefinitionScanner scanner;

/**
 * Create a new AnnotationConfigApplicationContext that needs to be populated
 * through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
 */
//默认构造函数,初始化一个空容器,容器不包含任何 Bean 信息,需要在稍后通过调用其register()
//方法注册配置类,并调用refresh()方法刷新容器,触发容器对注解Bean的载入、解析和注册过程
public AnnotationConfigApplicationContext() {
	this.reader = new AnnotatedBeanDefinitionReader(this);
	this.scanner = new ClassPathBeanDefinitionScanner(this);
}

/**
 * Create a new AnnotationConfigApplicationContext, deriving bean definitions
 * from the given annotated classes and automatically refreshing the context.
 * @param annotatedClasses one or more annotated classes,
 * e.g. {@link Configuration @Configuration} classes
 */
//最常用的构造函数,通过将涉及到的配置类传递给该构造函数,以实现将相应配置类中的Bean自动注册到容器中
public AnnotationConfigApplicationContext(Class... annotatedClasses) {
	this();
	register(annotatedClasses);
	refresh();
}

/**
 * Create a new AnnotationConfigApplicationContext, scanning for bean definitions
 * in the given packages and automatically refreshing the context.
 * @param basePackages the packages to check for annotated classes
 */
//该构造函数会自动扫描以给定的包及其子包下的所有类,并自动识别所有的Spring Bean,将其注册到容器中
public AnnotationConfigApplicationContext(String... basePackages) {
	this();
	scan(basePackages);
	refresh();
}

3.2、类参数构造执行

在执行熟悉的refresh方法之前,会先执行ApplicationContext中的register,进而执行AnnotatedBeanDefinitionReader中的register,最后执行doRegister。

在doRegister方法中,关键的步骤有几个:

  1. ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd),获取到Bean的作用域,是原型还是单例
  2. AnnotationConfigUtils.processCommonDefinitionAnnotations(abd),处理Bean上的其他注解
  3. definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry),完成BeanDefinitionHolder的构建,类似于XML方式,但在此处,将根据作用域参数决定对应的代理策略
  4. BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry),注册BeanDefinition信息。
public void register(Class... annotatedClasses) {
	Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
	this.reader.register(annotatedClasses);
}
public void register(Class... annotatedClasses) {
	for (Class annotatedClass : annotatedClasses) {
		registerBean(annotatedClass);
	}
}
public void registerBean(Class annotatedClass) {
	doRegisterBean(annotatedClass, null, null, null);
}
 void doRegisterBean(Class annotatedClass, @Nullable Supplier instanceSupplier, @Nullable String name,
		@Nullable Class[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

	//根据指定的注解Bean定义类,创建Spring容器中对注解Bean的封装的数据结构
	AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
	if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
		return;
	}

	abd.setInstanceSupplier(instanceSupplier);
	//解析注解Bean定义的作用域,若@Scope("prototype"),则Bean为原型类型;
	//若@Scope("singleton"),则Bean为单态类型
	ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
	//为注解Bean定义设置作用域
	abd.setScope(scopeMetadata.getScopeName());
	//为注解Bean定义生成Bean名称
	String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

	//处理注解Bean定义中的通用注解
	AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
	//如果在向容器注册注解Bean定义时,使用了额外的限定符注解,则解析限定符注解。
	//主要是配置的关于autowiring自动依赖注入装配的限定条件,即@Qualifier注解
	//Spring自动依赖注入装配默认是按类型装配,如果使用@Qualifier则按名称
	if (qualifiers != null) {
		for (Class qualifier : qualifiers) {
			//如果配置了@Primary注解,设置该Bean为autowiring自动依赖注入装//配时的首选
			if (Primary.class == qualifier) {
				abd.setPrimary(true);
			}
			//如果配置了@Lazy注解,则设置该Bean为非延迟初始化,如果没有配置,
			//则该Bean为预实例化
			else if (Lazy.class == qualifier) {
				abd.setLazyInit(true);
			}
			//如果使用了除@Primary和@Lazy以外的其他注解,则为该Bean添加一
			//个autowiring自动依赖注入装配限定符,该Bean在进autowiring
			//自动依赖注入装配时,根据名称装配限定符指定的Bean
			else {
				abd.addQualifier(new AutowireCandidateQualifier(qualifier));
			}
		}
	}
	for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
		customizer.customize(abd);
	}

	//创建一个指定Bean名称的Bean定义对象,封装注解Bean定义类数据
	BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
	//根据注解Bean定义类中配置的作用域,创建相应的代理对象
	definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
	//向IOC容器注册注解Bean类定义对象
	BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

3.2.1、作用域解析

AnnotationScopeMetadataResolver类

AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
                annDef.getMetadata(), this.scopeAnnotationType)方法将注解和注解值放入一个Map之中,AnnotationAttributes继承了LinkHashMap。

如果注解数值不为空,就可以将获取到的作用域值放入metadata,这个值在attributes.getEnum("proxyMode")之中获取到

public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
	ScopeMetadata metadata = new ScopeMetadata();
	if (definition instanceof AnnotatedBeanDefinition) {
		AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
		//从注解Bean定义类的属性中查找属性为”Scope”的值,即@Scope注解的值
		//annDef.getMetadata().getAnnotationAttributes()方法将Bean
		//中所有的注解和注解的值存放在一个map集合中
		AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
				annDef.getMetadata(), this.scopeAnnotationType);
		//将获取到的@Scope注解的值设置到要返回的对象中
		if (attributes != null) {
			metadata.setScopeName(attributes.getString("value"));
			//获取@Scope注解中的proxyMode属性值,在创建代理对象时会用到
			ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
			//如果@Scope的proxyMode属性为DEFAULT或者NO
			if (proxyMode == ScopedProxyMode.DEFAULT) {
				//设置proxyMode为NO
				proxyMode = this.defaultProxyMode;
			}
			//为返回的元数据设置proxyMode
			metadata.setScopedProxyMode(proxyMode);
		}
	}
	//返回解析的作用域元信息对象
	return metadata;
}

3.2.2、通用注解处理

AnnotationConfigUtils类

在这里对懒加载,首选项,名称加载等注解进行对应处理

static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
	AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
	//如果Bean定义中有@Lazy注解,则将该Bean预实例化属性设置为@lazy注解的值
	if (lazy != null) {
		abd.setLazyInit(lazy.getBoolean("value"));
	}

	else if (abd.getMetadata() != metadata) {
		lazy = attributesFor(abd.getMetadata(), Lazy.class);
		if (lazy != null) {
			abd.setLazyInit(lazy.getBoolean("value"));
		}
	}
	//如果Bean定义中有@Primary注解,则为该Bean设置为autowiring自动依赖注入装配的首选对象
	if (metadata.isAnnotated(Primary.class.getName())) {
		abd.setPrimary(true);
	}
	//如果Bean定义中有@ DependsOn注解,则为该Bean设置所依赖的Bean名称,
	//容器将确保在实例化该Bean之前首先实例化所依赖的Bean
	AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
	if (dependsOn != null) {
		abd.setDependsOn(dependsOn.getStringArray("value"));
	}

	if (abd instanceof AbstractBeanDefinition) {
		AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
		AnnotationAttributes role = attributesFor(metadata, Role.class);
		if (role != null) {
			absBd.setRole(role.getNumber("value").intValue());
		}
		AnnotationAttributes description = attributesFor(metadata, Description.class);
		if (description != null) {
			absBd.setDescription(description.getString("value"));
		}
	}
}

3.2.3、代理模式选择

AnnotationConfigUtils类

在这里根据作用域值的不同,对BeanDefinitionHolder做不同的处理

如果为ScopedProxyMode.NO就不做代理

如果为ScopedProxyMode.TARGET_CLASS,就为true

如果为ScopedProxyMode.INTERFACES,就为false

分别执行不同的策略

static BeanDefinitionHolder applyScopedProxyMode(
		ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {

	//获取注解Bean定义类中@Scope注解的proxyMode属性值
	ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
	//如果配置的@Scope注解的proxyMode属性值为NO,则不应用代理模式
	if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
		return definition;
	}
	//获取配置的@Scope注解的proxyMode属性值,如果为TARGET_CLASS
	//则返回true,如果为INTERFACES,则返回false
	boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
	//为注册的Bean创建相应模式的代理对象
	return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}

3.2.4、注册BeanDefinition

BeanDefinitionReaderUtils类,向IOC进行注册的方法:registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()),这个方法就是向DefaultListableBeanFactory中进行注册。

public static void registerBeanDefinition(
		BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
		throws BeanDefinitionStoreException {

	// Register bean definition under primary name.
	//获取解析的BeanDefinition的名称
	String beanName = definitionHolder.getBeanName();
	//向IOC容器注册BeanDefinition
	registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

	// Register aliases for bean name, if any.
	//如果解析的BeanDefinition有别名,向容器为其注册别名
	String[] aliases = definitionHolder.getAliases();
	if (aliases != null) {
		for (String alias : aliases) {
			registry.registerAlias(beanName, alias);
		}
	}
}

3.3、路径构造执行

跳转至ClassPathBeanDefinitionScanner,其中doScan方法是核心

Set candidates = findCandidateComponents(basePackage)方法获取到包和子包的类,下面的只是对BeanDefinition的一些处理

registerBeanDefinition(definitionHolder, this.registry),最终的处理方法,也是在XML中见过的,会跳转至工具类BeanDefinitionReaderUtils之中,最后存放到DefaultListableBeanFactory之中。

public void scan(String... basePackages) {
	Assert.notEmpty(basePackages, "At least one base package must be specified");
	this.scanner.scan(basePackages);
}
public int scan(String... basePackages) {
	//获取容器中已经注册的Bean个数
	int beanCountAtScanStart = this.registry.getBeanDefinitionCount();

	//启动扫描器扫描给定包
	doScan(basePackages);

	// Register annotation config processors, if necessary.
	//注册注解配置(Annotation config)处理器
	if (this.includeAnnotationConfig) {
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	}

	//返回注册的Bean个数
	return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}
//类路径Bean定义扫描器扫描给定包及其子包
protected Set doScan(String... basePackages) {
	Assert.notEmpty(basePackages, "At least one base package must be specified");
	//创建一个集合,存放扫描到Bean定义的封装类
	Set beanDefinitions = new LinkedHashSet<>();
	//遍历扫描所有给定的包
	for (String basePackage : basePackages) {
		//调用父类ClassPathScanningCandidateComponentProvider的方法
		//扫描给定类路径,获取符合条件的Bean定义
		Set candidates = findCandidateComponents(basePackage);
		//遍历扫描到的Bean
		for (BeanDefinition candidate : candidates) {
			//获取Bean定义类中@Scope注解的值,即获取Bean的作用域
			ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
			//为Bean设置注解配置的作用域
			candidate.setScope(scopeMetadata.getScopeName());
			//为Bean生成名称
			String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
			//如果扫描到的Bean不是Spring的注解Bean,则为Bean设置默认值,
			//设置Bean的自动依赖注入装配属性等
			if (candidate instanceof AbstractBeanDefinition) {
				postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
			}
			//如果扫描到的Bean是Spring的注解Bean,则处理其通用的Spring注解
			if (candidate instanceof AnnotatedBeanDefinition) {
				//处理注解Bean中通用的注解,在分析注解Bean定义类读取器时已经分析过
				AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
			}
			//根据Bean名称检查指定的Bean是否需要在容器中注册,或者在容器中冲突
			if (checkCandidate(beanName, candidate)) {
				BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
				//根据注解中配置的作用域,为Bean应用相应的代理模式
				definitionHolder =
						AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
				beanDefinitions.add(definitionHolder);
				//向容器注册扫描到的Bean
				registerBeanDefinition(definitionHolder, this.registry);
			}
		}
	}
	return beanDefinitions;
}

3.4、web版本

AnnotationConfigWebApplicationContext是AnnotationConfigApplicationContext的web版本,它重写了loadBeanDefinitions方法,在其中依旧使用了扫描器和读取器,具体不再继续赘述

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
	//为容器设置注解Bean定义读取器
	AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory);
	//为容器设置类路径Bean定义扫描器
	ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory);

	//获取容器的Bean名称生成器
	BeanNameGenerator beanNameGenerator = getBeanNameGenerator();
	//为注解Bean定义读取器和类路径扫描器设置Bean名称生成器
	if (beanNameGenerator != null) {
		reader.setBeanNameGenerator(beanNameGenerator);
		scanner.setBeanNameGenerator(beanNameGenerator);
		beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
	}

	//获取容器的作用域元信息解析器
	ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver();
	//为注解Bean定义读取器和类路径扫描器设置作用域元信息解析器
	if (scopeMetadataResolver != null) {
		reader.setScopeMetadataResolver(scopeMetadataResolver);
		scanner.setScopeMetadataResolver(scopeMetadataResolver);
	}

	if (!this.annotatedClasses.isEmpty()) {
		if (logger.isInfoEnabled()) {
			logger.info("Registering annotated classes: [" +
					StringUtils.collectionToCommaDelimitedString(this.annotatedClasses) + "]");
		}
		reader.register(this.annotatedClasses.toArray(new Class[this.annotatedClasses.size()]));
	}

	if (!this.basePackages.isEmpty()) {
		if (logger.isInfoEnabled()) {
			logger.info("Scanning base packages: [" +
					StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]");
		}
		scanner.scan(this.basePackages.toArray(new String[this.basePackages.size()]));
	}

	//获取容器定义的Bean定义资源路径
	String[] configLocations = getConfigLocations();
	//如果定位的Bean定义资源路径不为空
	if (configLocations != null) {
		for (String configLocation : configLocations) {
			try {
				//使用当前容器的类加载器加载定位路径的字节码类文件
				Class clazz = ClassUtils.forName(configLocation, getClassLoader());
				if (logger.isInfoEnabled()) {
					logger.info("Successfully resolved class for [" + configLocation + "]");
				}
				reader.register(clazz);
			}
			catch (ClassNotFoundException ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Could not load class for config location [" + configLocation +
							"] - trying package scan. " + ex);
				}
				//如果容器类加载器加载定义路径的Bean定义资源失败
				//则启用容器类路径扫描器扫描给定路径包及其子包中的类
				int count = scanner.scan(configLocation);
				if (logger.isInfoEnabled()) {
					if (count == 0) {
						logger.info("No annotated classes found for specified class/package [" + configLocation + "]");
					}
					else {
						logger.info("Found " + count + " annotated classes in package [" + configLocation + "]");
					}
				}
			}
		}
	}
}

你可能感兴趣的:(spring,进阶,源码,spring,java,eureka)