Spring源码学习(一) IOC容器

 Spring 提供的最基本的Ioc容器接口是BeanFactory,  通过BeanFactory可以获取bean对象的实例, 但BeanFactory 是怎么从配置文件里读取的bean对象的信息呢?

   下面的代码是BeanFactory去获取spring.xml配置的bean的实例:

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:访问网络资源的实现类。

ClassPathResource:访问类加载路径里资源的实现类。

FileSystemResource:访问文件系统里资源的实现类。

ServletContextResource:访问相对于 ServletContext 路径里的资源的实现类:

InputStreamResource:访问输入流资源的实现类。

ByteArrayResource:访问字节数组资源的实现类。


 上面的列子中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对象的过程,欢迎指正^^


你可能感兴趣的:(Spring源码学习(一) IOC容器)