spring源码学习(1)

网上有很多spring的源码分析教程,也有很多类图,但是spring的源码特别复杂,一层嵌套一层,刚开始看,很难受,越看越懵,所以我买了本书《spring源码深度解析》。跟着书的内容来学习吧。

首先是spring读取配置文件,spring有一个专门读取配置的较为顶级的接口-Resource。假设我们使用ClassPathResource进行resource的实例化。

//得到resource的实例
ClassPathResource resource=new ClassPathResource("beans.xml");

接着,既然有了resource实例,那么就需要分析里面的东西了。我们常用spring的时候,是使用xml的形式(不考虑springBoot),那么对应的工厂应该就是xmlFactory了。

ClassPathResource resource=new ClassPathResource("beans.xml");
//这里XmlBeanFactory在4.3.4里面已经过时了
XmlBeanFactory factory=new XmlBeanFactory(resource);
//ClassPathXmlApplicationConetext用于比xmlBeanFactory更加强大的功能。
/*
 *BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
 */
//由于书上是从xmlBeanFactory开始的,那么我们就用xmlBeanFactory开始分析
//到xmlBeanFactory的构造函数里。
public XmlBeanFactory(Resource resource) throws BeansException {
		this(resource, null);
}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
		//这里先不管
        super(parentBeanFactory);
        //由方法的名字分析,是为了加载bean吧
		this.reader.loadBeanDefinitions(resource);
}
//接着进入loadBeanDefinitions(resource)方法
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
		return loadBeanDefinitions(new EncodedResource(resource));//(1)
}
//再进去,关键性代码
//getResource是将(1)中的resource重新得到,可能是resource有编码的要求
InputStream inputStream = encodedResource.getResource().getInputStream();
	try {
		InputSource inputSource = new InputSource(inputStream);
		if (encodedResource.getEncoding() != null) {
			inputSource.setEncoding(encodedResource.getEncoding());
		}
        //继续进入
		return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
	}
	finally {
		inputStream.close();
}
//---------------------------------------------------------------------------------------
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
	try {
        //读方法,返回类型,大致猜测一下,应该是说对xml进行解析。返回解析过后的doc
		Document doc = doLoadDocument(inputSource, resource);
        //获取到正确的doc后,应该就是注册并加载bean了吧(重头戏)
		return registerBeanDefinitions(doc, resource);
    }
    //省略了诸多catch语句:解析失败过后的抛错
}

接下来查看重头戏:注册并加载bean。

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		//使用DefaultBeanDefinitionDocumentReader实例化BeanDefinitionDocumentReader 
        BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		//读方法名:统计之前的注册次数
        int countBefore = getRegistry().getBeanDefinitionCount();
		//加载并注册bean
        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));//(1)
		return getRegistry().getBeanDefinitionCount() - countBefore;
}
//继续进入(1)
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		logger.debug("Loading bean definitions");
		//root:得到节点
        Element root = doc.getDocumentElement();
        //哈哈,应该是核心了吧,真正的加载bean
		doRegisterBeanDefinitions(root);
}

protected void doRegisterBeanDefinitions(Element root) {
		
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);
        //profile的处理,判断是什么环境:这就达到了不同环境,不同配置文件的效果。
		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;
				}
			}
		}
        //解析前处理:空实现
		preProcessXml(root);
        //还没有注册bean,真的是很深。接着看
		parseBeanDefinitions(root, this.delegate);
		//解析后处理:空实现
        postProcessXml(root);

		this.delegate = parent;
}
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)) {
                        //spring的标签处理bean
						parseDefaultElement(ele, delegate);
					}
					else {
                        //自定义标签:处理bean
                        //这里我现在不想研究,等以后吧,因为目前学习的重点不在于此
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
}

 

    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/qq_40384690/article/details/81270453
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞