BeanDefinition的载入与注册

以下说法若有不对的地方欢迎大家指正

我这里用的是断点不断跟进的方式 

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);
	}

 

具体过程如上

这边只是阐述了一下这个过程 有兴趣的可以自己跟进查看更详细的解析过程

猜你喜欢

转载自fair-jm.iteye.com/blog/1846753