02-Spring源码——XML解析

一、基于XML的使用

如何把一个类交给Spring去管理,使用XML的实现方式:

创建一个Student类:

public class Student {
    private String name = "筱筱";

    private int age = 18;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

XML配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"

       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       ">

    <!-- 自定义扫描标签 -->
    <context:component-scan base-package="cn.spring.demo"/>

    <!-- 可以设置一些属性 -->
    <bean id="student" class="cn.spring.demo.bean.Student"></bean>
</beans>

测试类:

@Test
public void test1() {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    Student student = (Student) context.getBean("student");
    System.out.println(student);
}

测试结果:
在这里插入图片描述

二源码解析

进入ClassPathXmlApplicationContext类,看他的构造方法:

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
	this(new String[] {configLocation}, true, null);
}

调用了this,看其他构造方法:

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

	super(parent);
	// 给configLocations容器赋值
	setConfigLocations(configLocations);
	if (refresh) {
		// Spring的核心方法
		refresh();
	}
}

进入Spring的核心方法——AbstractApplicationContext.refresh():

@Override
public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// 1、为容器初始化做准备
		prepareRefresh();

		/*
		 * 2、基于XML配置文件的解析
		 * 2.1、创建BeanFactory对象
		 * 2.2、xml解析
		 * 	传统标签解析:bean、import等
		 * 	自定义标签解析 如:<context:component-scan base-package="com.xiangxue.jack"/>
		 * 	自定义标签解析流程:
		 * 		a、根据当前解析标签的头信息找到对应的namespaceUri
		 * 		b、加载spring所有jar中的spring.handlers文件。并建立映射关系
		 * 		c、根据namespaceUri从映射关系中找到对应的实现了NamespaceHandler接口的类
		 * 		d、调用类的init方法,init方法是注册了各种自定义标签的解析类
		 * 		e、根据namespaceUri找到对应的解析类,然后调用paser方法完成标签解析
		 *
		 * 2.3、把解析出来的xml标签封装成BeanDefinition对象
		 */
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// 3、给beanFactory设置一些属性值
		prepareBeanFactory(beanFactory);

		try {
			// Allows post-processing of the bean factory in context subclasses.
			postProcessBeanFactory(beanFactory);

			// 4、完成对BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor接口的调用
			invokeBeanFactoryPostProcessors(beanFactory);

			// 5、把实现了BeanPostProcessor接口的类实例化,并且加入到BeanFactory中
			registerBeanPostProcessors(beanFactory);

			// 6、国际化
			initMessageSource();

			// 7、初始化事件管理类
			initApplicationEventMulticaster();

			// 8、这个方法着重理解模板设计模式,因为在springboot中,这个方法是用来做内嵌tomcat启动的
			onRefresh();

			// 9、往事件管理类中注册事件类
			registerListeners();

			/*
			 * 10、这个方法是spring中最重要的方法,没有之一
			 *  所以这个方法一定要理解要具体看
			 *  10.1、bean实例化过程
			 *  10.2、ioc
			 *  10.3、注解支持
			 *  10.4、BeanPostProcessor的执行
			 *  10.5、Aop的入口
			 */
			// Instantiate all remaining (non-lazy-init) singletons.
			finishBeanFactoryInitialization(beanFactory);

			// Last step: publish corresponding event.
			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.
			destroyBeans();

			// Reset 'active' flag.
			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...
			resetCommonCaches();
		}
	}
}

这里主要看 obtainFreshBeanFactory() 方法,完成了XML的解析:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
	// 核心方法,必须读
	refreshBeanFactory();
	return getBeanFactory();
}

进入AbstractRefreshableApplicationContext.refreshBeanFactory()方法:

protected final void refreshBeanFactory() throws BeansException {
	// 如果BeanFactory不为空,则清除BeanFactory和里面的实例
	if (hasBeanFactory()) {
		destroyBeans();
		closeBeanFactory();
	}
	try {
		// BeanFactory 实例工厂
		DefaultListableBeanFactory beanFactory = createBeanFactory();
		beanFactory.setSerializationId(getId());
		// 设置是否可以循环依赖 allowCircularReferences
		// 是否允许使用相同名称重新注册不同的bean实现.
		customizeBeanFactory(beanFactory);
		// 解析xml,并把xml中的标签封装成BeanDefinition对象
		loadBeanDefinitions(beanFactory);
		this.beanFactory = beanFactory;
	} catch (IOException ex) {
		throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
	}
}

主要看AbstractXmlApplicationContext.loadBeanDefinitions()方法:

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
	// 创建xml的解析器,这里是一个委托模式
	XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

	// Configure the bean definition reader with this context's
	// resource loading environment.
	beanDefinitionReader.setEnvironment(this.getEnvironment());
	// 这里传一个this进去,因为ApplicationContext是实现了ResourceLoader接口的
	beanDefinitionReader.setResourceLoader(this);
	beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

	// Allow a subclass to provide custom initialization of the reader,
	// then proceed with actually loading the bean definitions.
	initBeanDefinitionReader(beanDefinitionReader);
	// 主要看这个方法
	loadBeanDefinitions(beanDefinitionReader);
}

主要看AbstractXmlApplicationContext.loadBeanDefinitions()方法:

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
	Resource[] configResources = getConfigResources();
	if (configResources != null) {
		reader.loadBeanDefinitions(configResources);
	}
	// 获取需要加载的xml配置文件
	String[] configLocations = getConfigLocations();
	if (configLocations != null) {
		// 主要看这个方法
		reader.loadBeanDefinitions(configLocations);
	}
}

主要看AbstractBeanDefinitionReader.loadBeanDefinitions()方法:

public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
	Assert.notNull(locations, "Location array must not be null");
	int count = 0;
	for (String location : locations) {
		// 主要看这个方法
		count += loadBeanDefinitions(location);
	}
	return count;
}

主要看AbstractBeanDefinitionReader.loadBeanDefinitions()方法,这里是一个空壳方法:

public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
	// 主要看这个方法
	return loadBeanDefinitions(location, null);
}

主要看AbstractBeanDefinitionReader.loadBeanDefinitions()方法:

public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
	ResourceLoader resourceLoader = getResourceLoader();
	if (resourceLoader == null) {
		throw new BeanDefinitionStoreException(
				"Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
	}

	if (resourceLoader instanceof ResourcePatternResolver) {
		// Resource pattern matching available.
		try {
			// 把字符串类型的xml文件路径,形如:classpath*:user/**/*-context.xml,转换成Resource对象类型,其实就是用流
			// 的方式加载配置文件,然后封装成Resource对象
			Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
			// 主要看这个方法
			int count = loadBeanDefinitions(resources);
			if (actualResources != null) {
				Collections.addAll(actualResources, resources);
			}
			if (logger.isTraceEnabled()) {
				logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
			}
			return count;
		} catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"Could not resolve bean definition resource pattern [" + location + "]", ex);
		}
	} else {
		// Can only load single resources by absolute URL.
		Resource resource = resourceLoader.getResource(location);
		int count = loadBeanDefinitions(resource);
		if (actualResources != null) {
			actualResources.add(resource);
		}
		if (logger.isTraceEnabled()) {
			logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
		}
		return count;
	}
}

主要看loadBeanDefinitions(Resource… resources)方法:

public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
	Assert.notNull(resources, "Resource array must not be null");
	int count = 0;
	for (Resource resource : resources) {
		// 模板设计模式,调用到子类中的方法
		count += loadBeanDefinitions(resource);
	}
	return count;
}

进入XmlBeanDefinitionReader.loadBeanDefinitions(Resource resource):

public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
	// EncodedResource带编码的对Resource对象的封装
	return loadBeanDefinitions(new EncodedResource(resource));
}

进入loadBeanDefinitions(EncodedResource encodedResource):

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

	Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();

	if (!currentResources.add(encodedResource)) {
		throw new BeanDefinitionStoreException(
				"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
	}

	// 获取Resource对象中的xml文件流对象
	try (InputStream inputStream = encodedResource.getResource().getInputStream()) {

		// InputSource是jdk中的sax xml文件解析对象
		InputSource inputSource = new InputSource(inputStream);
		if (encodedResource.getEncoding() != null) {
			inputSource.setEncoding(encodedResource.getEncoding());
		}
		// 主要看这个方法
		return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
	} catch (IOException ex) {
		throw new BeanDefinitionStoreException(
				"IOException parsing XML document from " + encodedResource.getResource(), ex);
	} finally {
		currentResources.remove(encodedResource);
		if (currentResources.isEmpty()) {
			this.resourcesCurrentlyBeingLoaded.remove();
		}
	}
}

主要看doLoadBeanDefinitions()方法:

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
		throws BeanDefinitionStoreException {

	try {
		// 把inputSource 封装成Document文件对象,这是jdk的API
		Document doc = doLoadDocument(inputSource, resource);

		// 主要看这个方法,根据解析出来的document对象,拿到里面的标签元素封装成BeanDefinition
		int count = registerBeanDefinitions(doc, resource);
		if (logger.isDebugEnabled()) {
			logger.debug("Loaded " + count + " bean definitions from " + resource);
		}
		return count;
	} 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);
	}
}

主要看registerBeanDefinitions(Document doc, Resource resource)方法:

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
	// 又来一记委托模式,BeanDefinitionDocumentReader委托这个类进行document的解析
	BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
	int countBefore = getRegistry().getBeanDefinitionCount();

	// 主要看这个方法,createReaderContext(resource) XmlReaderContext上下文,封装了XmlBeanDefinitionReader对象
	documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
	return getRegistry().getBeanDefinitionCount() - countBefore;
}

主要看DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(Document doc, XmlReaderContext readerContext)方法:

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
	this.readerContext = readerContext;
	//主要看这个方法,把root节点传进去
	doRegisterBeanDefinitions(doc.getDocumentElement());
}

主要看doRegisterBeanDefinitions(Element root)方法:

protected void doRegisterBeanDefinitions(Element root) {
	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);
			// We cannot use Profiles.of(...) since profile expressions are not supported
			// in XML config. See SPR-12458 for details.
			if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
							"] not matching: " + getReaderContext().getResource());
				}
				return;
			}
		}
	}

	preProcessXml(root);
	// 主要看这个方法,标签具体解析过程
	parseBeanDefinitions(root, this.delegate);
	postProcessXml(root);

	this.delegate = parent;
}

主要看parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)方法:

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
	if (delegate.isDefaultNamespace(root)) {
		NodeList nl = root.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (node instanceof Element) {
				Element ele = (Element) node;
				if (delegate.isDefaultNamespace(ele)) {
					// 默认标签解析
					parseDefaultElement(ele, delegate);
				} else {
					// 自定义标签解析
					delegate.parseCustomElement(ele);
				}
			}
		}
	} else {
		delegate.parseCustomElement(root);
	}
}

默认标签的解析

主要看parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)方法:

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标签,重要程度
	else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
		processBeanDefinition(ele, delegate);
	}
	else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
		// recurse
		doRegisterBeanDefinitions(ele);
	}
}

主要看processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)方法:

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
	// 重点看这个方法,解析document,封装成BeanDefinition
	BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
	if (bdHolder != null) {
		// 该方法功能不重要,设计模式重点看一下,装饰者设计模式,加上SPI设计思想
		bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
		try {
			// 完成document到BeanDefinition对象转换后,对BeanDefinition对象进行缓存注册
			// Register the final decorated instance.
			BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
		}
		catch (BeanDefinitionStoreException ex) {
			getReaderContext().error("Failed to register bean definition with name '" +
					bdHolder.getBeanName() + "'", ele, ex);
		}
		// Send registration event.
		getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
	}
}

解析document对象并封装成BeanDefinition

主要看BeanDefinitionParserDelegate.parseBeanDefinitionElement(Element ele)方法,是一个空壳方法:

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

主要看parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean)方法:

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
	String id = ele.getAttribute(ID_ATTRIBUTE);
	String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

	List<String> aliases = new ArrayList<>();
	if (StringUtils.hasLength(nameAttr)) {
		String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
		aliases.addAll(Arrays.asList(nameArr));
	}

	String beanName = id;
	if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
		beanName = aliases.remove(0);
		if (logger.isTraceEnabled()) {
			logger.trace("No XML 'id' specified - using '" + beanName +
					"' as bean name and " + aliases + " as aliases");
		}
	}

	// 检查beanName是否重复
	if (containingBean == null) {
		checkNameUniqueness(beanName, aliases, ele);
	}

	// <bean>标签解析的核心方法
	AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
	if (beanDefinition != null) {
		if (!StringUtils.hasText(beanName)) {
			try {
				if (containingBean != null) {
					beanName = BeanDefinitionReaderUtils.generateBeanName(
							beanDefinition, this.readerContext.getRegistry(), true);
				} else {
					beanName = this.readerContext.generateBeanName(beanDefinition);
					// 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.
					String beanClassName = beanDefinition.getBeanClassName();
					if (beanClassName != null &&
							beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
							!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
						aliases.add(beanClassName);
					}
				}
				if (logger.isTraceEnabled()) {
					logger.trace("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);
	}

	return null;
}

主要看parseBeanDefinitionElement()方法:

public AbstractBeanDefinition parseBeanDefinitionElement(
		Element ele, String beanName, @Nullable BeanDefinition containingBean) {

	this.parseState.push(new BeanEntry(beanName));

	String className = null;
	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 {
		// 创建GenericBeanDefinition对象
		AbstractBeanDefinition bd = createBeanDefinition(className, parent);

		// 解析bean标签的属性,并把解析出来的属性设置到BeanDefinition对象中
		parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
		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中的constructor-arg标签
		parseConstructorArgElements(ele, bd);
		// 解析bean中的property标签
		parsePropertyElements(ele, bd);
		// 可以不看,用不到
		parseQualifierElements(ele, bd);

		bd.setResource(this.readerContext.getResource());
		bd.setSource(extractSource(ele));

		return bd;
	} catch (ClassNotFoundException ex) {
		error("Bean class [" + className + "] not found", ele, ex);
	} catch (NoClassDefFoundError err) {
		error("Class that bean class [" + className + "] depends on not found", ele, err);
	} catch (Throwable ex) {
		error("Unexpected failure during bean definition parsing", ele, ex);
	} finally {
		this.parseState.pop();
	}

	return null;
}

解析Bean标签的属性,并把解析出来的属性设置到BeanDefinition对象中,主要看parseBeanDefinitionAttributes()方法:

public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
		@Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {

	if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
		error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
	}
	else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
		bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
	}
	else if (containingBean != null) {
		// Take default from containing bean in case of an inner bean definition.
		bd.setScope(containingBean.getScope());
	}

	if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
		bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
	}

	String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
	if (isDefaultValue(lazyInit)) {
		lazyInit = this.defaults.getLazyInit();
	}
	bd.setLazyInit(TRUE_VALUE.equals(lazyInit));

	String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
	bd.setAutowireMode(getAutowireMode(autowire));

	if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
		String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
		bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
	}

	String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
	if (isDefaultValue(autowireCandidate)) {
		String candidatePattern = this.defaults.getAutowireCandidates();
		if (candidatePattern != null) {
			String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
			bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
		}
	}
	else {
		bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
	}

	if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
		bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
	}

	if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
		String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
		bd.setInitMethodName(initMethodName);
	}
	else if (this.defaults.getInitMethod() != null) {
		bd.setInitMethodName(this.defaults.getInitMethod());
		bd.setEnforceInitMethod(false);
	}

	if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
		String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
		bd.setDestroyMethodName(destroyMethodName);
	}
	else if (this.defaults.getDestroyMethod() != null) {
		bd.setDestroyMethodName(this.defaults.getDestroyMethod());
		bd.setEnforceDestroyMethod(false);
	}

	if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
		bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
	}
	if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
		bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
	}

	return bd;
}

SPI思想

详见自定标签的解析

对BeanDefinition对象进行缓存注册

主要看BeanDefinitionReaderUtils.registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)方法:

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

	// Register bean definition under primary name.
	String beanName = definitionHolder.getBeanName();
	// 完成BeanDefinition的注册
	registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

	// 建立别名和 id的映射,这样就可以根据别名获取到id
	// Register aliases for bean name, if any.
	String[] aliases = definitionHolder.getAliases();
	if (aliases != null) {
		for (String alias : aliases) {
			registry.registerAlias(beanName, alias);
		}
	}
}

主要看DefaultListableBeanFactory.registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法:

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
		throws BeanDefinitionStoreException {

	Assert.hasText(beanName, "Bean name must not be empty");
	Assert.notNull(beanDefinition, "BeanDefinition must not be null");

	if (beanDefinition instanceof AbstractBeanDefinition) {
		try {
			((AbstractBeanDefinition) beanDefinition).validate();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
					"Validation of bean definition failed", ex);
		}
	}

	// 先判断BeanDefinition是否已经注册
	BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
	if (existingDefinition != null) {
		if (!isAllowBeanDefinitionOverriding()) {
			throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
		} else if (existingDefinition.getRole() < beanDefinition.getRole()) {
			// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
			if (logger.isInfoEnabled()) {
				logger.info("Overriding user-defined bean definition for bean '" + beanName +
						"' with a framework-generated bean definition: replacing [" +
						existingDefinition + "] with [" + beanDefinition + "]");
			}
		} else if (!beanDefinition.equals(existingDefinition)) {
			if (logger.isDebugEnabled()) {
				logger.debug("Overriding bean definition for bean '" + beanName +
						"' with a different definition: replacing [" + existingDefinition +
						"] with [" + beanDefinition + "]");
			}
		} else {
			if (logger.isTraceEnabled()) {
				logger.trace("Overriding bean definition for bean '" + beanName +
						"' with an equivalent definition: replacing [" + existingDefinition +
						"] 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;
				removeManualSingletonName(beanName);
			}
		} else {
			// 把beanDefinition缓存到map中
			// Still in startup registration phase
			this.beanDefinitionMap.put(beanName, beanDefinition);
			// 把beanName放到beanDefinitionNames list中,这个list着重记住,bean实例化的时候需要用到
			this.beanDefinitionNames.add(beanName);
			removeManualSingletonName(beanName);
		}
		this.frozenBeanDefinitionNames = null;
	}

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

beanDefinition对象的注册其实就是把beanName和beanDefinition对象的对应关系放到beanDefinitionMap中,以及把beanName放入beanDefinitionNames容器中,此时完成了默认标签的解析,为实例化做准备。

自定义标签的解析

回到DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)方法进入自定义标签解析的流程:

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
	if (delegate.isDefaultNamespace(root)) {
		NodeList nl = root.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (node instanceof Element) {
				Element ele = (Element) node;
				if (delegate.isDefaultNamespace(ele)) {
					// 默认标签解析
					parseDefaultElement(ele, delegate);
				} else {
					// 自定义标签解析
					delegate.parseCustomElement(ele);
				}
			}
		}
	} else {
		delegate.parseCustomElement(root);
	}
}

进入BeanDefinitionParserDelegate.parseCustomElement(Element ele)方法:

public BeanDefinition parseCustomElement(Element ele) {
	// 主要看这个方法
	return parseCustomElement(ele, null);
}

主要看parseCustomElement(Element ele, @Nullable BeanDefinition containingBd)方法:

public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
	// 根据标签获取到namespaceUri
	String namespaceUri = getNamespaceURI(ele);
	if (namespaceUri == null) {
		return null;
	}
	// 进入此方法resolve,根据namespaceUri进行匹配解析类
	NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
	if (handler == null) {
		error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
		return null;
	}
	// 进行解析
	return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

根据namespaceUri找解析类

主要看DefaultNamespaceHandlerResolver.resolve(String namespaceUri)方法:

public NamespaceHandler resolve(String namespaceUri) {
	// 获取spring中所有jar包里面的 "META-INF/spring.handlers"文件,并且建立映射关系
	Map<String, Object> handlerMappings = getHandlerMappings();
	// 根据namespaceUri:http://www.springframework.org/schema/context,获取到这个命名空间的处理类
	Object handlerOrClassName = handlerMappings.get(namespaceUri);
	if (handlerOrClassName == null) {
		return null;
	} else if (handlerOrClassName instanceof NamespaceHandler) {
		return (NamespaceHandler) handlerOrClassName;
	} else {
		String className = (String) handlerOrClassName;
		try {
			Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
			if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
				throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
						"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
			}
			NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);

			// 调用处理类的init方法,在init方法中完成标签元素解析类的注册
			namespaceHandler.init();
			handlerMappings.put(namespaceUri, namespaceHandler);
			return namespaceHandler;
		} catch (ClassNotFoundException ex) {
			throw new FatalBeanException("Could not find NamespaceHandler class [" + className +
					"] for namespace [" + namespaceUri + "]", ex);
		} catch (LinkageError err) {
			throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" +
					className + "] for namespace [" + namespaceUri + "]", err);
		}
	}
}

以这个标签为例<context:component-scan base-package=“cn.spring.demo”/>
调用ContextNamespaceHandler的init()方法,建立解析类的映射关系:

public void init() {
		registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
		registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
		registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
		registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
		registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
		registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
		registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
	}

主要看这一行(registerBeanDefinitionParser(“component-scan”, new ComponentScanBeanDefinitionParser())😉
解析类的对应关系就建立好啦。。。。。。

解析

回到BeanDefinitionParserDelegate.parseCustomElement(Element ele, @Nullable BeanDefinition containingBd)方法中的return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd))方法,看解析步骤:
在这里插入图片描述
会进入NamespaceHandlerSupport.parse(Element element, ParserContext parserContext)方法:

public BeanDefinition parse(Element element, ParserContext parserContext) {
	BeanDefinitionParser parser = findParserForElement(element, parserContext);
	// 主要看parse(element, parserContext)
	return (parser != null ? parser.parse(element, parserContext) : null);
}

以’component-scan’为例,会进入ComponentScanBeanDefinitionParser.parse(Element element, ParserContext parserContext)方法:

public BeanDefinition parse(Element element, ParserContext parserContext) {
		// 获取basePackage属性
		String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
		basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
		// 可以用逗号分开
		String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
				ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

		// Actually scan for bean definitions and register them.
		// 创建注解扫描器
		ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
		// 扫描并把扫描的类封装成beanDefinition对象  核心方法
		Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
		// 注册组件
		registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

		return null;
	}
创建包扫描器

进入核心方法configureScanner(parserContext, element):
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

进入核心方法doScan(String… basePackages):

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
	Assert.notEmpty(basePackages, "At least one base package must be specified");
	Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
	for (String basePackage : basePackages) {
		// 扫描到有注解的类并封装成BeanDefinition对象
		Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
		for (BeanDefinition candidate : candidates) {
			ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
			candidate.setScope(scopeMetadata.getScopeName());
			String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
			if (candidate instanceof AbstractBeanDefinition) {
				// 支持了@Lazy @DependOn注解
				postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
			}
			if (candidate instanceof AnnotatedBeanDefinition) {
				AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
			}
			if (checkCandidate(beanName, candidate)) {
				BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
				definitionHolder =
						AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
				beanDefinitions.add(definitionHolder);
				// BeanDefinition注册
				registerBeanDefinition(definitionHolder, this.registry);
			}
		}
	}
	return beanDefinitions;
}
扫描有注解的类,并封装成BeanDefinition对象

进入方法findCandidateComponents(String basePackage):

public Set<BeanDefinition> findCandidateComponents(String basePackage) {
	if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
		return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
	} else {
		// 核心方法
		return scanCandidateComponents(basePackage);
	}
}

进入方法scanCandidateComponents(basePackage):

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
	Set<BeanDefinition> candidates = new LinkedHashSet<>();
	try {
		String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
				resolveBasePackage(basePackage) + '/' + this.resourcePattern;
		// 这里递归寻找文件
		Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
		boolean traceEnabled = logger.isTraceEnabled();
		boolean debugEnabled = logger.isDebugEnabled();
		for (Resource resource : resources) {
			if (traceEnabled) {
				logger.trace("Scanning " + resource);
			}
			if (resource.isReadable()) {
				try {
					// 包装了类的基本信息的对象
					MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
					// 如果类上面有includeFilters注解
					if (isCandidateComponent(metadataReader)) {
						ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
						sbd.setSource(resource);
						if (isCandidateComponent(sbd)) {
							if (debugEnabled) {
								logger.debug("Identified candidate component class: " + resource);
							}
							candidates.add(sbd);
						} else {
							if (debugEnabled) {
								logger.debug("Ignored because not a concrete top-level class: " + resource);
							}
						}
					} else {
						if (traceEnabled) {
							logger.trace("Ignored because not matching any filter: " + resource);
						}
					}
				} catch (Throwable ex) {
					throw new BeanDefinitionStoreException(
							"Failed to read candidate component class: " + resource, ex);
				}
			} else {
				if (traceEnabled) {
					logger.trace("Ignored because not readable: " + resource);
				}
			}
		}
	} catch (IOException ex) {
		throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
	}
	return candidates;
}

递归扫描文件,PathMatchingResourcePatternResolver.getResources():
在这里插入图片描述
递归寻找.class文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
扫描完 .class 后封装成ScannedGenericBeanDefinition:
在这里插入图片描述
填充beanDefinition的属性:
在这里插入图片描述
完成注册:实际就是添加beanfactory的beanDefinitionMap和beanDefinitionNames容器中,流程和默认标签解析一致,详看registerBeanDefinition(definitionHolder, this.registry)方法;

注册完beanDefinition后注册组件

ConfigurationClassPostProcessor.class
AutowiredAnnotationBeanPostProcessor.class
CommonAnnotationBeanPostProcessor.class
EventListenerMethodProcessor.class
DefaultEventListenerFactory.class
在这里插入图片描述
在这里插入图片描述
ConfigurationClassPostProcessor.class组件的注册:
在这里插入图片描述
在这里插入图片描述
AutowiredAnnotationBeanPostProcessor.class:组件的注册
在这里插入图片描述
在这里插入图片描述
CommonAnnotationBeanPostProcessor.class:组件的注册
在这里插入图片描述
在这里插入图片描述

EventListenerMethodProcessor.class:组件的注册
在这里插入图片描述
在这里插入图片描述

DefaultEventListenerFactory.class:组件的注册
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值