您的位置:首页 > 编程语言 > Java开发

Spring源码学习(一) IOC容器

2014-07-09 00:00 507 查看
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对象的过程,欢迎指正^^
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: