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

编写测试类:

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>继承

接口继承



 

实体



 

时序图

<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中

猜你喜欢

转载自smallbug-vip.iteye.com/blog/2282054