以下说法若有不对的地方欢迎大家指正
我这里用的是断点不断跟进的方式
spring的版本为3.2.2
以下是一张方法的调用图 方便理解
最近在看spring的IoC具体实现
其实也没有什么太大的心得 就是不断进行断点调试 然后看一下过程
这个过程其实并不复杂 只是一层层不断调用有点头晕罢了
以下我来说说具体的BeanDefinition载入和注册的过程
首先我这边是以ClassPathXmlApplicationContext为IoC容器的 他底下是维护了一个DefaultListableBeanFactory
bean的注册工作其实是在DefaultListableBeanFactory中完成的
这个Map的定义和实现如下:
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
这边是主要的过程(如果我写错了 谢谢指正^_^)
1、 通过XML解析接到Document对象标准的(org.w3c.dom.Document)
2、 在documentReader中实现这个按照Spring的Bean规则进行解析的过程
3、 实际的解析工作是交给documentReader中的BeanDefinitionParserDelegate完成的
4、 BeanDefinitionParserDelegate把解析的beanDefinition交给BeanDefinitionHolder
5、 在documentReader中调用BeanDefinitionReaderUtils.registerBeanDefinition(,)向IoC容器中注册
为了直观 我把一些主要的代码放出来并写上自己的注释 以下:
// XmlBeanDefinitionsReader中的方法 protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { int validationMode = getValidationModeForResource(resource); // 标准的org.w3c.dom.Document对象 Document doc = this.documentLoader.loadDocument( inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware()); // 完成标准的document到spring定义的bean规则解析的过程 return registerBeanDefinitions(doc, resource); } catch (BeanDefinitionStoreException ex) { ... ...
// 同样是XmlBeanDefinitionsReader中的方法 public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { // 得到一个BeanDefinitionDocumentReader的对象来按照bean规则解析 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); documentReader.setEnvironment(this.getEnvironment()); // 获取解析前的bean数目 第一次的话应该是0 int countBefore = getRegistry().getBeanDefinitionCount(); // 具体的解析过程以下完成 documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; }
// 以上的documentReader.registerBeanDefinitions(,)方法调用了DefaultBeanDefinitionDocumentReader中的方法 public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; logger.debug("Loading bean definitions"); // 得到根元素 Element root = doc.getDocumentElement(); // 这边开始做解析 doRegisterBeanDefinitions(root); }
// 同样是调用了DefaultBeanDefinitionDocumentReader中的方法
protected void doRegisterBeanDefinitions(Element root) {
// 这部分是关于profile的(spring 3.1之后才有的吧?) 绕过
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
Assert.state(this.environment != null, "Environment must be set for evaluating profiles");
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!this.environment.acceptsProfiles(specifiedProfiles)) {
return;
}
}
// 解析中做着核心工作的就是BeanDefinitionParserDelegate的对象
// Any nested <beans> elements will cause recursion in this method. In
// order to propagate and preserve <beans> default-* attributes correctly,
// keep track of the current (parent) delegate, which may be null. Create
// the new (child) delegate with a reference to the parent for fallback purposes,
// then ultimately reset this.delegate back to its original (parent) reference.
// this behavior emulates a stack of delegates without actually necessitating one.
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createHelper(this.readerContext, root, parent);
// 在DefaultBeanDefinitionDocumentReader中什么都不做
preProcessXml(root);
// 这边就是具体的解析了
parseBeanDefinitions(root, this.delegate);
// 在DefaultBeanDefinitionDocumentReader中什么都不做
postProcessXml(root);
// 还原
this.delegate = parent;
}
// DefaultBeanDefinitionDocumentReader中的方法 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)) { parseDefaultElement(ele, delegate); } else { delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }
// 以上方法的parseDefaultElement如下 同样是DefaultBeanDefinitionDocumentReader中的方法 // 根据不同的名称执行不同的操作 private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { importBeanDefinitionResource(ele); } else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { processAliasRegistration(ele); } else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { processBeanDefinition(ele, delegate); } else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // recurse doRegisterBeanDefinitions(ele); } }
//同样是DefaultBeanDefinitionDocumentReader中的方法 这是以上的processBeanDefinition(ele, delegate) protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { // bdHolder就是BeanDefinitionHolder // 解析实际都是靠BeanDefinitionParserDelegate中的方法完成的 这里面的代码太多了就不跟进了 // 需要的可以自己去看下 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // Register the final decorated instance. // 这句话就是向BeanFactory注册bean BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex); } // Send registration event. getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }
// BeanDefinitionReaderUtils中的静态方法 public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // Register bean definition under primary name. String beanName = definitionHolder.getBeanName(); // 传入的这个registry其实就是在之前的DefaultListableBeanFactory实例 因为 // DefaultListableBeanFactory实现了BeanDefinitionRegistry接口可以注册bean registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // Register aliases for bean name, if any. String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String aliase : aliases) { registry.registerAlias(beanName, aliase); } } }
// DefaultListableBeanFactory中的方法 public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { Assert.hasText(beanName, "Bean name must not be empty"); Assert.notNull(beanDefinition, "BeanDefinition must not be null"); if (beanDefinition instanceof AbstractBeanDefinition) { try { ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex); } } synchronized (this.beanDefinitionMap) { Object oldBeanDefinition = this.beanDefinitionMap.get(beanName); // 如果存在了同名的bean if (oldBeanDefinition != null) { //如果不允许bean的覆盖的话就会抛出异常 if (!this.allowBeanDefinitionOverriding) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound."); } else { if (this.logger.isInfoEnabled()) { this.logger.info("Overriding bean definition for bean '" + beanName + "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } } else { this.beanDefinitionNames.add(beanName); this.frozenBeanDefinitionNames = null; } // 可以看到其实内部还是一个Map的结构来维护的 this.beanDefinitionMap.put(beanName, beanDefinition); } resetBeanDefinition(beanName); }
具体过程如上
这边只是阐述了一下这个过程 有兴趣的可以自己跟进查看更详细的解析过程