spring IOC源码分析(2)

        refresh这个方法包含了整个BeanFactory初始化的过程,定位资源由obtainFreshBeanFactory()来完成,
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}

         可以看到其调用了refreshBeanFactory(),refreshBeanFactory()在这个类中是抽象方法,其实现在AbstractRefreshableApplicationContext中。

protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(beanFactory);
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			……
		}
}

          在这个方法中,先判断BeanFactory是否存在,如果存在则先销毁beans并关闭beanFactory,接着创建DefaultListableBeanFactory,并调用loadBeanDefinitions(beanFactory)装载bean定义。loadBeanDefinitions方法同样是抽象方法,是由其子类实现的,也即在AbstractXmlApplicationContext中。

	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {  
	    // 这里使用XMLBeanDefinitionReader来载入bean定义信息的XML文件  
	    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);  
	  
	    //这里配置reader的环境,其中ResourceLoader是我们用来定位bean定义信息资源位置的  
	    //因为上下文本身实现了ResourceLoader接口,所以可以直接把上下文作为ResourceLoader传递给XmlBeanDefinitionReader  
	    beanDefinitionReader.setResourceLoader(this);  
	    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));  
	  
	    initBeanDefinitionReader(beanDefinitionReader);  
	    //这里转到定义好的XmlBeanDefinitionReader中对载入bean信息进行处理  
	    loadBeanDefinitions(beanDefinitionReader);  
	}  

          接着我们转到beanDefinitionReader中进行处理

	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {  
	    Resource[] configResources = getConfigResources();  
	    if (configResources != null) {  
	        //调用XmlBeanDefinitionReader来载入bean定义信息。  
	        reader.loadBeanDefinitions(configResources);  
	    }  
	    String[] configLocations = getConfigLocations();  
	    if (configLocations != null) {  
	        reader.loadBeanDefinitions(configLocations);  
	    }  
	}  

         可以到org.springframework.beans.factory.support看一下BeanDefinitionReader的结构

        在其抽象父类AbstractBeanDefinitionReader中定义了载入过程

 

	public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {  
	    //这里得到当前定义的ResourceLoader,默认的我们使用DefaultResourceLoader  
	    ResourceLoader resourceLoader = getResourceLoader();  
	    //如果没有找到我们需要的ResourceLoader,直接抛出异常  
	    if (resourceLoader instanceof ResourcePatternResolver) {  
	        // 这里处理我们在定义位置时使用的各种pattern,需要 ResourcePatternResolver来完成  
	        try {  
	            Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);  
	            int loadCount = loadBeanDefinitions(resources);  
	            return loadCount;  
	        }  
	        ........  
	    }  
	    else {  
	        // 这里通过ResourceLoader来完成位置定位  
	        Resource resource = resourceLoader.getResource(location);  
              // 这里已经把一个位置定义转化为Resource接口,可以供XmlBeanDefinitionReader来使用了  
	        int loadCount = loadBeanDefinitions(resource);  
	        return loadCount;  
	    }  
	} 



 


        看到第8、16行,结合上面的ResourceLoader与ApplicationContext的继承关系图,可以知道此时调用的是DefaultResourceLoader中的getSource()方法定位Resource,因为ClassPathXmlApplicationContext本身就是DefaultResourceLoader的实现类,所以此时又回到了ClassPathXmlApplicationContext中来。

 

        继续回到XmlBeanDefinitionReader的loadBeanDefinitions(Resource …)方法看得到代表bean文件的资源定义以后的载入过程。

	public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {  
	    .......  
	    try {  
	        //这里通过Resource得到InputStream的IO流  
	        InputStream inputStream = encodedResource.getResource().getInputStream();  
	        try {  
	            //从InputStream中得到XML的解析源  
	            InputSource inputSource = new InputSource(inputStream);  
	            if (encodedResource.getEncoding() != null) {  
	                inputSource.setEncoding(encodedResource.getEncoding());  
	            }  
	            //这里是具体的解析和注册过程  
	            return doLoadBeanDefinitions(inputSource, encodedResource.getResource());  
	        }  
	        finally {  
	            //关闭从Resource中得到的IO流  
	            inputStream.close();  
	        }  
	    }  
	       .........  
	}  
	  
	protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)  
	        throws BeanDefinitionStoreException {  
	    try {  
	        int validationMode = getValidationModeForResource(resource);  
	        //通过解析得到DOM,然后完成bean在IOC容器中的注册  
	        Document doc = this.documentLoader.loadDocument(  
	                inputSource, this.entityResolver, this.errorHandler, validationMode, this.namespaceAware);  
	        return registerBeanDefinitions(doc, resource);  
	    }  
	.......  
	}

        在doLoadBeanDefinitions(…)先把定义文件解析为DOM对象,然后进行具体的注册过程。

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
 		//具体的注册过程,首先得到XmlBeanDefinitionDocumentReader来处理xml的bean定义文件
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		documentReader.setEnvironment(this.getEnvironment());
		int countBefore = getRegistry().getBeanDefinitionCount();
		//调用注册方法
                     documentReader.registerBeanDefinitions(doc,createReaderContext(resource));
	         return getRegistry().getBeanDefinitionCount() - countBefore;
}

 

 

        具体的过程在BeanDefinitionDocumentReader中完成,在DefaultBeanDefinitionDocumentReader的方法中完成bean定义文件的解析和IOC容器中bean的初始化。

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;

		logger.debug("Loading bean definitions");
		Element root = doc.getDocumentElement();

		doRegisterBeanDefinitions(root);
}

 

protected void doRegisterBeanDefinitions(Element root) {
		……(注:省略号表示省略掉了代码)
		//通过代理delegate解析
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createHelper(readerContext, root, parent);

		preProcessXml(root);
		parseBeanDefinitions(root, this.delegate);
		postProcessXml(root);

		this.delegate = parent;
}

 

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		if (delegate.isDefaultNamespace(root)) {
			//得到xml文件的子节点,比如各个bean节点
			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)) {
						//这里是解析过程的调用,对缺省的元素进行分析比如bean元素
						parseDefaultElement(ele, delegate);
					}
					else {
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
}

 

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		//对元素Import进行处理
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		//对我们熟悉的bean元素进行处理
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
}
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		//委托给BeanDefinitionParserDelegate来完成对bean元素的处理,这个类包括了具体的bean解析过程。把解析bean文件得到的信息放在BeanDefinition里,它是bean信息的主要载体,也是IOC容器的管理对象。
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
	         bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
	                           //向IOC容器注册,实际是放到IOC容器的一个map里		 
                                    BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				……
			}
			// Send registration event.
			//这里向IOC容器发送事件,表示解析和注册完成
	                     getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
}

         可以看到在processBeanDefinition中对具体bean元素的解析是交给BeanDefinitionParserDelegate来完成的。我们接着看其实现的函数:

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
		……(省略)
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		if (beanDefinition != null) {
			//BeanDefinition解析过程
                                ……(省略)
			String[] aliasesArray = StringUtils.toStringArray(aliases);
                           //将解析完的bean定义包装后返回
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
		}
		return null;
}

 


         在这里对定义文件中的bean元素进行解析,得到AbstractBeanDefinition,并用BeanDefinitionHolder封装后返回。

        下面我们看解析完的bean如何在IOC容器中注册:在BeanDefinitionReaderUtils中调用的是:

public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
		// Register bean definition under primary name.
		//得到需要注册bean的名字
		String beanName = definitionHolder.getBeanName();
		//调用IOC来注册bean的过程,需要得到BeanDefinition
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		//将别名通过IOC容器和bean联系起来进行注册
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String aliase : aliases) {
				registry.registerAlias(beanName, aliase);
			}
		}
}


         接着我们看看bean的注册实现,从上面看到其调用的是BeanDefinitionRegistry的方法registerBeanDefinition完成注册,跟踪代码可知BeanFactory容器的一个实现DefaultListableBeanFactory实现了这个接口并提供了注册的具体实现:

 

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {

		......
		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				//抛出异常BeanDefinitionStoreException
				……
			}
		}

		synchronized (this.beanDefinitionMap) {
			Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
			if (oldBeanDefinition != null) {
				if (!this.allowBeanDefinitionOverriding) {
					//抛出异常BeanDefinitionStoreException
					……
				}
				else {
					if (this.logger.isInfoEnabled()) {
						……
					}
				}
			}
			else {
				this.beanDefinitionNames.add(beanName);
				this.frozenBeanDefinitionNames = null;
			}
			this.beanDefinitionMap.put(beanName, beanDefinition);

			resetBeanDefinition(beanName);
		}
}

         可以看到整个注册过程很简单,就是将bean添加到BeanDefinition的map中。这样就完成了bean定义在IOC容器中的注册,就可被IOC容器进行管理和使用了。


 

 


 


 

 

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值