Spring源碼學習(一) IOC容器

 Spring 提供的最基本的Ioc容器接口是BeanFactory,  經過BeanFactory能夠獲取bean對象的實例, 但BeanFactory 是怎麼從配置文件裏讀取的bean對象的信息呢?java

   下面的代碼是BeanFactory去獲取spring.xml配置的bean的實例:spring

package com.younchen.test;

import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import com.younchen.model.Person;



public class GetBeanTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		 //Spring IOC 容器之一BeanFactory
		//獲取資源文件
		Resource resource=new ClassPathResource("spring.xml");
		//bean工廠
		DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
                //reader
		XmlBeanDefinitionReader reader=new XmlBeanDefinitionReader(beanFactory);
		//reader去讀取資源文件
		reader.loadBeanDefinitions(resource);
		//獲取bean對象
		Person person=(Person) beanFactory.getBean("person");
		person.setName("youn");
		
		System.out.println(person.getName());
		

	}

}

  

 看一下Resource變量,Spring裏提供了Resource接口,它是抽象資源接口,classpath中的bean.xml ,spring.xml 均可以描述爲抽象資源。數組

Resource 接口有如下的實例:網絡

UrlResource:訪問網絡資源的實現類。ide

ClassPathResource:訪問類加載路徑裏資源的實現類。this

FileSystemResource:訪問文件系統裏資源的實現類。spa

ServletContextResource:訪問相對於 ServletContext 路徑裏的資源的實現類:debug

InputStreamResource:訪問輸入流資源的實現類。code

ByteArrayResource:訪問字節數組資源的實現類。xml


 上面的列子中Resource獲取的實例是ClassPathResource,該類用於讀取類加載路徑(classpath)中的spring.xml,接下來建立BeanFactory 這個時候新建立的beanFactory還不能直接使用,由於beanFactory沒有獲取到配置文件信息, 讀取配置文件的工做是由Resource完成,而解析的時候由BeanDefinitionReader來完成。 實例化beanDefinitionReader時須要將beanFactory傳遞進去,目的是將解析後的bean信息傳給beanFactory。  接下來beanDefinitionReader去解析Resource讀取到的配置文件,這一步完成之後beanFactory就能夠工做了,簡單描述步驟就是:


1.建立Ioc容器抽象資源

2.建立一個BeanFactory 

3.將配置文件解析器配置給BeanFactory

4.解析器去讀取配置文件

5.BeanFacotory獲取指定的bean對象實例


  下面簡單介紹一下ApplicationContext 即上下文, 上面的例子能夠看出BeanFactory並無資源定義的能力,

 他須要解析器去解析以後配置給BeanFactory, 而ApplicationContext卻擁有對資源的定義能力,更確切的說 Application包含了BeanFactory ,先看下代碼:

package com.younchen.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.younchen.model.PersonModel;
import com.younchen.util.SpringUtil;

public class ApplicationContextTest {

	
	public static void main(String[] args){
		
		
	  ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
	  
	  PersonModel personModel =(PersonModel) context.getBean("personModel");
	  
	  personModel.getPerson().setName("黑貓");
	  personModel.showPersonName();
	}


 上面的代碼是上下文去獲取配置文件定義的bean對象的實例,能夠經過debug模式跟進去看Application的建立過程,

實例化的過程他會調用refresh方法:

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();
			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
                        //...........省略
		}
	}

 

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()這一句代碼建立並配置BeanFactory,

繼續追蹤會到:

@Override
	protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			 DefaultListableBeanFactory beanFactory = createBeanFactory();
		         customizeBeanFactory(beanFactory);
		         loadBeanDefinitions(beanFactory);
		         // ............省略
			}
		}
		catch (IOException ex) {
                       //..............省略
		}
	}

try語句中第一行代碼 createBeanFactory()方法是建立BeanFactory的一個實例, 再往下走到loadBeanDefinitions(beanFactory)方法 ,loadBeanDefinitions應該比較熟悉了吧? 用來解析配置文件的,代碼以下:

@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
		// Configure the bean definition reader with this context's
		// resource loading environment.
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// Allow a subclass to provide custom initialization of the reader,
		// then proceed with actually loading the bean definitions.
		initBeanDefinitionReader(beanDefinitionReader);
		loadBeanDefinitions(beanDefinitionReader);
	}

這個方法中 首先實例化了BeanDefinitionReader  ,以後經過loadBeanDefinitions 方法讀取配置文件 代碼以下:

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}

到此就完成了 ApplicationContext 內置的BeanFactory的建立,及將配置文件配置給BeanFactory

當ApplicationContext執行getBean()方法時 實際上執行的是BeanFactory的getBean方法。


 以上是Spring上下文獲取配置文件中bean對象的過程,歡迎指正^^

相關文章
相關標籤/搜索