spring源码解析之IOC容器(二)------加载和注册
2020-12-13 03:36
标签:ecif 自定义 store stat fallback linked different edm 效率 上一篇跟踪了IOC容器对配置文件的定位,现在我们继续跟踪代码,看看IOC容器是怎么加载和注册配置文件中的信息的。开始之前,首先我们先来了解一下IOC容器所使用的数据结构-------BeanDefinition,它是一个上层接口,有很多实现类,分别对应不同的数据载体。我们平时开发的时候,也会定义很多pojo类,来作为获取数据的载体。最常见的就是,从数据库中获取数据之后,使用一个定义的pojo来装载,然后我们就可以在程序中使用这个pojo类来编写各种业务逻辑。同样,IOC容器首先会读取配置的XML中各个节点,即各个标签元素,然后根据不同的标签元素,使用不同的数据结构来装载该元素中的各种属性的值。比如我们最熟悉的 先回到上篇资源的定位那里,代码如下: 进入loadBeanDefinitions(resource)方法,正式开始加载源码的跟踪: 进入doLoadBeanDefinitions(inputSource, encodedResource.getResource())方法: 继续进入registerBeanDefinitions(doc, resource)方法: 进入registerBeanDefinitions(doc, createReaderContext(resource))方法: 进入doRegisterBeanDefinitions(root)方法: 这里也用到了模板方法,preProcessXml(root)和postProcessXml(root)这两个方法都是空实现,是留给客户来实现自己的逻辑的。重点研究一下parseBeanDefinitions(root, this.delegate)方法: parseCustomElement(root)方法不需要怎么研究,我们平时几乎不会用到自定义的标签,所以只跟踪parseDefaultElement(ele, delegate)里面的代码: 可以看到,对于不同的标签,spring采用不同的策略进行处理,重点跟踪一下处理bean标签的方法processBeanDefinition(ele, delegate): 在这个方法中,delegate.parseBeanDefinitionElement(ele)是解析bean元素中各种属性的方法,registerBeanDefinition(bdHolder, getReaderContext().getRegistry())是将封装好的数据进行存储的方法。先看一下解析的方法: 我们可以得到如下信息: 1、获取bean标签的id属性和name属性的值; 2、name属性是可以都有多个值的,以逗号或者分号分割; 3、如果id没有赋值,则取name的第一个值作为id的值。所以,我们一般都会给id赋值,这样效率高一些; 4、检查以这个id标识的bean是不是唯一的; 5、进行其他属性的解析,并最终封装测AbstractBeanDefinition对象,也就是我们前文中提到的数据结构; 6、最后封装成BeanDefinitionHolder对象之后返回。 进入parseBeanDefinitionElement(ele, beanName, containingBean)方法,看一下其他元素的解析过程: 解析封装成BeanDefinitionHolder对象之后,就可以进行注册了,先回到之前的processBeanDefinition(ele, delegate): 现在进入BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())方法进行分析: 这里的beanName就是之前封装好的bean的id。这个方法中分别以id和别名作为key来注册bean,其实就是存储在map中。 进入registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()),在其子类DefaultListableBeanFactory中有实现: 我们可以看到:这个beanDefinitionMap就是用来存储解析好的bean的,以id作为key。至此,就将所有的bean标签解析好之后封装成BeanDefinition注册到了IOC容器中。但是,到目前为止,IOC容器并没有为我们将这些解析好的数据生成一个一个bean实例,我们仍然不能就这样直接使用。下一篇接着跟踪。 spring源码解析之IOC容器(二)------加载和注册 标签:ecif 自定义 store stat fallback linked different edm 效率 原文地址:https://www.cnblogs.com/helei123/p/11080191.html 1 public int loadBeanDefinitions(String location, Set
1 @Override
2 public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
3 return loadBeanDefinitions(new EncodedResource(resource));
4 }
1 public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
2 Assert.notNull(encodedResource, "EncodedResource must not be null");
3 if (logger.isInfoEnabled()) {
4 logger.info("Loading XML bean definitions from " + encodedResource);
5 }
6
7 Set
1 protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
2 throws BeanDefinitionStoreException {
3 try {
4 Document doc = doLoadDocument(inputSource, resource);
5 return registerBeanDefinitions(doc, resource);
6 }
7 catch (BeanDefinitionStoreException ex) {
8 throw ex;
9 }
10 catch (SAXParseException ex) {
11 throw new XmlBeanDefinitionStoreException(resource.getDescription(),
12 "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
13 }
14 catch (SAXException ex) {
15 throw new XmlBeanDefinitionStoreException(resource.getDescription(),
16 "XML document from " + resource + " is invalid", ex);
17 }
18 catch (ParserConfigurationException ex) {
19 throw new BeanDefinitionStoreException(resource.getDescription(),
20 "Parser configuration exception parsing XML from " + resource, ex);
21 }
22 catch (IOException ex) {
23 throw new BeanDefinitionStoreException(resource.getDescription(),
24 "IOException parsing XML document from " + resource, ex);
25 }
26 catch (Throwable ex) {
27 throw new BeanDefinitionStoreException(resource.getDescription(),
28 "Unexpected exception parsing XML document from " + resource, ex);
29 }
30 }
1 public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
2 //此时documentReader已经是DefaultBeanDefinitionDocumentReader类了
3 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
4 int countBefore = getRegistry().getBeanDefinitionCount();
5 documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
6 //返回当前注册的beanDefinition的个数
7 return getRegistry().getBeanDefinitionCount() - countBefore;
8 }
1 public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
2 this.readerContext = readerContext;
3 logger.debug("Loading bean definitions");
4 Element root = doc.getDocumentElement();
5 doRegisterBeanDefinitions(root);
6 }
1 protected void doRegisterBeanDefinitions(Element root) {
2 // Any nested
1 protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
2 if (delegate.isDefaultNamespace(root)) {
3 NodeList nl = root.getChildNodes();
4 for (int i = 0; i ) {
5 Node node = nl.item(i);
6 if (node instanceof Element) {
7 Element ele = (Element) node;
8 if (delegate.isDefaultNamespace(ele)) {
9 parseDefaultElement(ele, delegate);
10 }
11 else {
12 delegate.parseCustomElement(ele);
13 }
14 }
15 }
16 }
17 else {
18 delegate.parseCustomElement(root);
19 }
20 }
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);
}
//beans标签
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
1 protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
2 //委托给delegate去进行各种标签的解析,parseBeanDefinitionElement方法中包含了各种标签元素的解析,
3 //并将解析好的内容封装成BeanDefinitionHolder对象
4 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
5 if (bdHolder != null) {
6 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
7 try {
8 // Register the final decorated instance.
9 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
10 }
11 catch (BeanDefinitionStoreException ex) {
12 getReaderContext().error("Failed to register bean definition with name ‘" +
13 bdHolder.getBeanName() + "‘", ele, ex);
14 }
15 // Send registration event.
16 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
17 }
18 }
1 public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
2 //获取bean标签的id属性的值
3 String id = ele.getAttribute(ID_ATTRIBUTE);
4 //获取bean标签上name属性的值
5 String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
6
7 List
1 public AbstractBeanDefinition parseBeanDefinitionElement(
2 Element ele, String beanName, BeanDefinition containingBean) {
3
4 this.parseState.push(new BeanEntry(beanName));
5
6 String className = null;
7 if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
8 className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
9 }
10
11 try {
12 String parent = null;
13 if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
14 parent = ele.getAttribute(PARENT_ATTRIBUTE);
15 }
16 AbstractBeanDefinition bd = createBeanDefinition(className, parent);
17
18 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
19 bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
20
21 parseMetaElements(ele, bd);
22 parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
23 parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
24
25 parseConstructorArgElements(ele, bd);
26 parsePropertyElements(ele, bd);
27 parseQualifierElements(ele, bd);
28
29 bd.setResource(this.readerContext.getResource());
30 bd.setSource(extractSource(ele));
31
32 return bd;
33 }
34 catch (ClassNotFoundException ex) {
35 error("Bean class [" + className + "] not found", ele, ex);
36 }
37 catch (NoClassDefFoundError err) {
38 error("Class that bean class [" + className + "] depends on not found", ele, err);
39 }
40 catch (Throwable ex) {
41 error("Unexpected failure during bean definition parsing", ele, ex);
42 }
43 finally {
44 this.parseState.pop();
45 }
46
47 return null;
48 }
1 protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
2 //委托给delegate去进行各种标签的解析,parseBeanDefinitionElement方法中包含了各种标签元素的解析,
3 //并将解析好的内容封装成BeanDefinitionHolder对象
4 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
5 if (bdHolder != null) {
6 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
7 try {
8 // Register the final decorated instance.
9 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
10 }
11 catch (BeanDefinitionStoreException ex) {
12 getReaderContext().error("Failed to register bean definition with name ‘" +
13 bdHolder.getBeanName() + "‘", ele, ex);
14 }
15 // Send registration event.
16 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
17 }
18 }
1 public static void registerBeanDefinition(
2 BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
3 throws BeanDefinitionStoreException {
4
5 // Register bean definition under primary name.
6 String beanName = definitionHolder.getBeanName();
7 registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
8
9 // Register aliases for bean name, if any.
10 String[] aliases = definitionHolder.getAliases();
11 if (aliases != null) {
12 for (String alias : aliases) {
13 registry.registerAlias(beanName, alias);
14 }
15 }
16 }
1 public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
2 throws BeanDefinitionStoreException {
3
4 Assert.hasText(beanName, "Bean name must not be empty");
5 Assert.notNull(beanDefinition, "BeanDefinition must not be null");
6
7 if (beanDefinition instanceof AbstractBeanDefinition) {
8 try {
9 ((AbstractBeanDefinition) beanDefinition).validate();
10 }
11 catch (BeanDefinitionValidationException ex) {
12 throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
13 "Validation of bean definition failed", ex);
14 }
15 }
16
17 BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
18 if (existingDefinition != null) {
19 if (!isAllowBeanDefinitionOverriding()) {
20 throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
21 "Cannot register bean definition [" + beanDefinition + "] for bean ‘" + beanName +
22 "‘: There is already [" + existingDefinition + "] bound.");
23 }
24 else if (existingDefinition.getRole() beanDefinition.getRole()) {
25 // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
26 if (logger.isWarnEnabled()) {
27 logger.warn("Overriding user-defined bean definition for bean ‘" + beanName +
28 "‘ with a framework-generated bean definition: replacing [" +
29 existingDefinition + "] with [" + beanDefinition + "]");
30 }
31 }
32 else if (!beanDefinition.equals(existingDefinition)) {
33 if (logger.isInfoEnabled()) {
34 logger.info("Overriding bean definition for bean ‘" + beanName +
35 "‘ with a different definition: replacing [" + existingDefinition +
36 "] with [" + beanDefinition + "]");
37 }
38 }
39 else {
40 if (logger.isDebugEnabled()) {
41 logger.debug("Overriding bean definition for bean ‘" + beanName +
42 "‘ with an equivalent definition: replacing [" + existingDefinition +
43 "] with [" + beanDefinition + "]");
44 }
45 }
46 this.beanDefinitionMap.put(beanName, beanDefinition);
47 }
48 else {
49 if (hasBeanCreationStarted()) {
50 // Cannot modify startup-time collection elements anymore (for stable iteration)
51 synchronized (this.beanDefinitionMap) {
52 this.beanDefinitionMap.put(beanName, beanDefinition);
53 List
上一篇:Extjs树形控件入门
下一篇:基于JAVA的设计模式之组合模式
文章标题:spring源码解析之IOC容器(二)------加载和注册
文章链接:http://soscw.com/essay/27917.html