spring source learning (1)

There are a lot of spring source code analysis tutorials and class diagrams on the Internet, but the source code of spring is very complex, one layer is nested, and it's hard to see at the beginning. The more you look, the more muddled you become. So I bought the book "spring source code deep analysis". Follow the book to learn.

First, spring reads the configuration file. Spring has a top-level interface, resource, that reads the configuration. Suppose we use ClassPathResource to instantiate resource.

//Get an instance of resource
ClassPathResource resource=new ClassPathResource("beans.xml");

Then, since you have a resource instance, you need to analyze the contents. When we often use spring, we use the form of xml (regardless of springBoot), so the corresponding factory should be xmlFactory.

ClassPathResource resource=new ClassPathResource("beans.xml");
//Here XmlBeanFactory is out of date in 4.3.4
XmlBeanFactory factory=new XmlBeanFactory(resource);
//The above two lines of code can be replaced by the following, which roughly means to synthesize two steps into one step
/*
 *BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
 */
//Since the book starts with xmlBeanFactory, we use xmlBeanFactory to start the analysis
//Go to the xmlBeanFactory constructor.
public XmlBeanFactory(Resource resource) throws BeansException {
		this(resource, null);
}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
		//It doesn't matter here
        super(parentBeanFactory);
        //The name of the method is used to load the bean
		this.reader.loadBeanDefinitions(resource);
}
//Then go to the loadbean definitions (resource) method
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
		return loadBeanDefinitions(new EncodedResource(resource));//(1)
}
//Again, key code
//getResource is to get the resource in (1) again. It may be that the resource has coding requirements
InputStream inputStream = encodedResource.getResource().getInputStream();
	try {
		InputSource inputSource = new InputSource(inputStream);
		if (encodedResource.getEncoding() != null) {
			inputSource.setEncoding(encodedResource.getEncoding());
		}
        //Continue to enter
		return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
	}
	finally {
		inputStream.close();
}
//---------------------------------------------------------------------------------------
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
	try {
        //Read method, return type, roughly guess, it should be to parse xml. Return the parsed doc
		Document doc = doLoadDocument(inputSource, resource);
        //After getting the correct doc, you should register and load the bean (play)
		return registerBeanDefinitions(doc, resource);
    }
    //Omit many catch statements: throw errors after parsing failure
}

Next let's look at the play: register and load the bean s.

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		//Instantiate BeanDefinitionDocumentReader with DefaultBeanDefinitionDocumentReader 
        BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		//Read method name: count the number of previous registrations
        int countBefore = getRegistry().getBeanDefinitionCount();
		//Load and register bean s
        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));//(1)
		return getRegistry().getBeanDefinitionCount() - countBefore;
}
//Continue to (1)
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		logger.debug("Loading bean definitions");
		//root: get node
        Element root = doc.getDocumentElement();
        //Ha ha, it should be the core, the real load bean
		doRegisterBeanDefinitions(root);
}

protected void doRegisterBeanDefinitions(Element root) {
		
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);
        //profile processing, determine what environment: this achieves the effect of different environments, different configuration files.
		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;
				}
			}
		}
        //Parsing preprocessing: empty implementation
		preProcessXml(root);
        //I'll go. I haven't registered bean yet. It's really deep. Then look
		parseBeanDefinitions(root, this.delegate);
		//Post parsing: empty implementation
        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)) {
                        //Processing bean
						parseDefaultElement(ele, delegate);
					}
					else {
                        //Processing bean
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
}

 

Keywords: Spring xml SpringBoot

Added by Dumps on Mon, 27 Jan 2020 17:58:13 +0200