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

20 篇文章 1 订阅
11 篇文章 0 订阅

目录

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<Resource> 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<EncodedResource> 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<EncodedResource> 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 <beans> elements will cause recursion in this method. In
	// order to propagate and preserve <beans> 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) {
	//如果元素节点是<Import>导入元素,进行导入解析
	if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
		importBeanDefinitionResource(ele);
	}
	//如果元素节点是<Alias>别名元素,进行别名解析
	else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
		processAliasRegistration(ele);
	}
	//元素节点既不是导入元素,也不是别名元素,即普通的<Bean>元素,
	//按照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对象中<Bean>元素的解析由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) {
	//获取<Bean>元素中的id属性值
	String id = ele.getAttribute(ID_ATTRIBUTE);
	//获取<Bean>元素中的name属性值
	String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

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

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

	String beanName = id;
	//如果<Bean>元素中没有配置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");
		}
	}

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

	//详细对<Bean>元素中配置的Bean定义进行解析的地方
	AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
	if (beanDefinition != null) {
		if (!StringUtils.hasText(beanName)) {
			try {
				if (containingBean != null) {
					//如果<Bean>元素中没有配置id、别名或者name,且没有包含子元素
					//<Bean>元素,为解析的Bean生成一个唯一beanName并注册
					beanName = BeanDefinitionReaderUtils.generateBeanName(
							beanDefinition, this.readerContext.getRegistry(), true);
				}
				else {
					//如果<Bean>元素中没有配置id、别名或者name,且包含了子元素
					//<Bean>元素,为解析的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) {
	//记录解析的<Bean>
	this.parseState.push(new BeanEntry(beanName));

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

	//如果<Bean>元素中配置了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 {
		//根据<Bean>元素配置的class名称和parent属性值创建BeanDefinition
		//为载入Bean定义信息做准备
		AbstractBeanDefinition bd = createBeanDefinition(className, parent);

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

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

		//解析<Bean>元素的构造方法设置
		parseConstructorArgElements(ele, bd);
		//解析<Bean>元素的<property>设置
		parsePropertyElements(ele, bd);
		//解析<Bean>元素的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();
	}

	//解析<Bean>元素出错时,返回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<String, BeanDefinition> 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<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
				updatedDefinitions.addAll(this.beanDefinitionNames);
				updatedDefinitions.add(beanName);
				this.beanDefinitionNames = updatedDefinitions;
				if (this.manualSingletonNames.contains(beanName)) {
					Set<String> 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);
}
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
		@Nullable Class<? extends Annotation>[] 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<? extends Annotation> 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<BeanDefinition> 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<BeanDefinitionHolder> doScan(String... basePackages) {
	Assert.notEmpty(basePackages, "At least one base package must be specified");
	//创建一个集合,存放扫描到Bean定义的封装类
	Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
	//遍历扫描所有给定的包
	for (String basePackage : basePackages) {
		//调用父类ClassPathScanningCandidateComponentProvider的方法
		//扫描给定类路径,获取符合条件的Bean定义
		Set<BeanDefinition> 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 + "]");
					}
				}
			}
		}
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值