欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

sping4.1.x IOC容器资源Bean注册流程详解

程序员文章站 2022-05-24 08:46:20
...

编写测试类:

package cn.smallbug.spring.testioc;

public interface PersonService {

	public void save();
}
public class PersonServiceImpl implements PersonService {

	public PersonServiceImpl(){
		System.out.println("3333333333333");
	}
	@Override
	public void save() {
		System.out.println("person save!");
	}

}
<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-4.1.xsd">

	<bean id="personService" class="cn.smallbug.spring.testioc.PersonServiceImpl"></bean>

</beans>
package cn.smallbug.spring.testioc;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class Testioc {

	@Test
	public void test01() {
		ApplicationContext context = //
		new FileSystemXmlApplicationContext(//
				"E:/eclipseWorkspace/WorkSpace01/spring/src/test/resources/testioc.xml");
		PersonService service = (PersonService) context.getBean("personService");
		service.save();
	}
}

 <1>继承

接口继承


sping4.1.x IOC容器资源Bean注册流程详解
            
    
    博客分类: Spring spingioc源码 
 

实体


sping4.1.x IOC容器资源Bean注册流程详解
            
    
    博客分类: Spring spingioc源码 
 

 

时序图

 

<2>流程

定位资源:

 

类:FileSystemXmlApplicationContext

方法:Constructor

1) setConfigLocations(configLocations); //设置资源地址字符串(XML文件地址)

2) refresh(); //调用基类的refresh()方法

 

类:AbstractApplicationContext

方法:refresh()

3) obtainFreshBeanFactory()

方法:obtainFreshBeanFactory

4) refreshBeanFactory()

 

类:AbstractRefreshableApplicationContext

方法:refreshBeanFactory()

5) createBeanFactory(); //创建DefaultListableBeanFactory对象,作为实际的IOC容器

6) loadBeanDefinitions(beanFactory); //模板方法模式调用子类实现

 

类:AbstractXmlApplicationContext

方法:loadBeanDefinitions(DefaultListableBeanFactory beanFactory)

7) new XmlBeanDefinitionReader(beanFactory); //创建读取资源的Reader类

8) loadBeanDefinitions(beanDefinitionReader);

方法:loadBeanDefinitions(XmlBeanDefinitionReader reader)

9) reader.loadBeanDefinitions(configLocations);//这个方法有两种情况,分别处理Resource资源和String资源

 

类:AbstractBeanDefinitionReader

方法:loadBeanDefinitions(String... locations)

10) for (String location : locations) {

counter += loadBeanDefinitions(location);

}

方法:loadBeanDefinitions(String location)

11) return loadBeanDefinitions(location, null);

 

方法:loadBeanDefinitions(String location, Set<Resource> actualResources)

12) ResourceLoader resourceLoader = getResourceLoader();//该对象将String转化为Resource

13) ((ResourcePatternResolver) resourceLoader).getResources(location);//转换资源AbstractApplicationContext

 

类:AbstractApplicationContext

方法:getResources(String locationPattern)

14) return this.resourcePatternResolver.getResources(locationPattern);

 

类:PathMatchingResourcePatternResolver

方法:getResources(String locationPattern)

15) return new Resource[] {getResourceLoader().getResource(locationPattern)};

 

类:DefaultResourceLoader

方法:getResource(String location)

16) return getResourceByPath(location);

 

类:FileSystemXmlApplicationContext

方法:getResourceByPath(String path)

17) return new FileSystemResource(path);//创建一个Resource并返回

 

 

 

加载资源:

类:AbstractBeanDefinitionReader

方法:loadBeanDefinitions(String location, Set<Resource> actualResources)

18) int loadCount = loadBeanDefinitions(resources);

方法:loadBeanDefinitions(Resource... resources)

19) for (Resource resource : resources) {

counter += loadBeanDefinitions(resource);//循环加载注册资源

}

 

类:XmlBeanDefinitionReader

方法:loadBeanDefinitions(EncodedResource encodedResource)

20) InputStream inputStream = encodedResource.getResource().getInputStream();//创建IO流

21) return doLoadBeanDefinitions(inputSource, encodedResource.getResource());

方法:doLoadBeanDefinitions(InputSource inputSource, Resource resource)

22) Document doc = doLoadDocument(inputSource, resource);//将读入的资源转化为Docuemnt

23) return registerBeanDefinitions(doc, resource);

方法:registerBeanDefinitions(Document doc, Resource resource)

24) BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();

25) documentReader.registerBeanDefinitions(doc, createReaderContext(resource));

 

类:DefaultBeanDefinitionDocumentReader

方法:registerBeanDefinitions(Document doc, XmlReaderContext readerContext)

26) Element root = doc.getDocumentElement();将Document转化为Element

27) doRegisterBeanDefinitions(root);

方法:doRegisterBeanDefinitions(Element root)

28) this.delegate = createDelegate(getReaderContext(), root, parent);//很重要,解析Element使用的就是这个对象

29) parseBeanDefinitions(root, this.delegate);

方法:parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)

30) NodeList nl = root.getChildNodes();

for (int i = 0; i < nl.getLength(); i++) {//逐条解析,对应每一个Bean

Node node = nl.item(i);

if (node instanceof Element) {

Element ele = (Element) node;

if (delegate.isDefaultNamespace(ele)) {

parseDefaultElement(ele, delegate);//解析import,alias,bean,beans

}

else {

delegate.parseCustomElement(ele);

}

}

}

方法:parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)

31) processBeanDefinition(ele, delegate);//解析bean

方法: processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)

32) BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);

方法: parseBeanDefinitionElement(Element ele, BeanDefinition containingBean)

33) String id = ele.getAttribute(ID_ATTRIBUTE);//读取ID

34) String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);//读取name

35) AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);//进一步解析

36) return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);//将解析好的BeanDefinition装入BeanDefinitionHolder

 

注册资源

类:DefaultBeanDefinitionDocumentReader

方法:processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)

37) BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

 

类:DefaultListableBeanFactory

方法:registerBeanDefinition(String beanName, BeanDefinition beanDefinition)

38) this.beanDefinitionNames.add(beanName);

this.manualSingletonNames.remove(beanName);

this.frozenBeanDefinitionNames = null;

this.beanDefinitionMap.put(beanName, beanDefinition);

 

定义如下:

/** List of bean definition names, in registration order */

private final List<String> beanDefinitionNames = new ArrayList<String>(64);

/** List of names of manually registered singletons, in registration order */

private final Set<String> manualSingletonNames = new LinkedHashSet<String>(16);

/** Map of bean definition objects, keyed by bean name */

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);

可见最终bean资源其实是注册到了BeanFactory子类的一个ConcurrentHashMap中

 

 

 

  • sping4.1.x IOC容器资源Bean注册流程详解
            
    
    博客分类: Spring spingioc源码 
  • 大小: 223.4 KB
  • sping4.1.x IOC容器资源Bean注册流程详解
            
    
    博客分类: Spring spingioc源码 
  • 大小: 6.1 KB
相关标签: sping ioc 源码