Spring核心学习(4)从XML中读取BeanDefinition-将代码变成配置

原创 2015年05月10日 17:49:31

前导:开始学习Spring核心思想,通过一个山寨精简版Spring代码结合学习。


内容:1. BeanDefinitionReader-配置读取者。 2. XmlBeanDefinitionReader-从XML中读取配置。 3. Resource-定位资源文件。这次将Bean的配置信息都放到了XML里,所以这里会有一个XML文件的读取,我们通过XmlBeanDefinitionReader将XML中的信息组装好成BeanDefinition放到一个Map里,这样我们就能真正做到像Spring那样靠配置文件来组装Bean。


重复的代码不再列出

BeanDefinition:

public class BeanDefinition {
	
	private Object bean;
	
	private Class beanClass;
	
	private String beanClassName;

	private PropertyValues propertyValues = new PropertyValues();
	
	public BeanDefinition() {}

	public Object getBean() {
		return bean;
	}

	public void setBean(Object bean) {
		this.bean = bean;
	}

	public Class getBeanClass() {
		return beanClass;
	}

	public void setBeanClass(Class beanClass) {
		this.beanClass = beanClass;
	}

	public String getBeanClassName() {
		return beanClassName;
	}

	public void setBeanClassName(String beanClassName) {
		this.beanClassName = beanClassName;
		try {
			this.beanClass = Class.forName(beanClassName);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} 
	}

	public PropertyValues getPropertyValues() {
		return propertyValues;
	}

	public void setPropertyValues(PropertyValues propertyValues) {
		this.propertyValues = propertyValues;
	}
	
}

Resource:

/**
 * Resource是spring内部定位资源接口
 * @author acer
 */
public interface Resource {
	
	InputStream getInputStream() throws IOException;
}
ResourceLoader:

public class ResourceLoader {
	
	public Resource getResource(String location) {
		URL resource = this.getClass().getClassLoader().getResource(location);
		return new UrlResource(resource);
	}
}
UrlResource:

public class UrlResource implements Resource{
	private final URL url;
	
	public UrlResource(URL url) {
		this.url = url;
	}

	@Override
	public InputStream getInputStream() throws IOException {
		URLConnection urlConnection = url.openConnection();
		urlConnection.connect();
		return urlConnection.getInputStream();
	}

}
BeanDefinitionReader:

/**
 * 从配置中读取BeanDefinitionReader
 * @author acer
 *
 */
public interface BeanDefinitionReader {
	
	void loadBeanDefinitions(String location) throws Exception;
	
}
AbstractBeanDefinitionReader:

/**
 * 从配置中读取BeanDefinitionReader
 * @author acer
 *
 */
public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader{
	
	private Map<String, BeanDefinition> registry;
	
	private ResourceLoader resourceLoader;
	
	protected AbstractBeanDefinitionReader(ResourceLoader resourceLoader) {
		this.registry = new HashMap<String, BeanDefinition>();
		this.resourceLoader = resourceLoader;
	} 
	
	public Map<String, BeanDefinition> getRegistry() {
		return this.registry;
	}

	public ResourceLoader getResourceLoader() {
		return resourceLoader;
	}

}

XmlBeanDefinitionReader:

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader{
	
	public XmlBeanDefinitionReader(ResourceLoader resourceLoader) {
		super(resourceLoader);
	}

	@Override
	public void loadBeanDefinitions(String location) throws Exception {
		InputStream inputStream = getResourceLoader().getResource(location).getInputStream();
		doLoadBeanDefinitions(inputStream);
	}

	protected void doLoadBeanDefinitions(InputStream inputStream) throws Exception {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder docBuilder = factory.newDocumentBuilder();
		Document doc = docBuilder.parse(inputStream);
		//解析bean
		registerBeanDefinitions(doc);
		inputStream.close();
	}
	
	public void registerBeanDefinitions(Document doc) {
		Element root = doc.getDocumentElement();
		parseBeanDefinitions(root);
	}
	
	protected void parseBeanDefinitions(Element 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;
				processBeanDefinition(ele);
			}
		}
	}
	
	protected void processBeanDefinition(Element ele) {
		String name = ele.getAttribute("name");
		String className = ele.getAttribute("class");
		BeanDefinition beanDefinition = new BeanDefinition();
		processProperty(ele, beanDefinition);
		beanDefinition.setBeanClassName(className);
		getRegistry().put(name, beanDefinition);
	}
	
	private void processProperty(Element ele, BeanDefinition beanDefinition) {
		NodeList propertyNode = ele.getElementsByTagName("property");
		for (int i = 0; i < propertyNode.getLength(); i++) {
			Node node = propertyNode.item(i);
			if (node instanceof Element) {
				Element propertyEle = (Element) node;
				String name = propertyEle.getAttribute("name");
				String value = propertyEle.getAttribute("value");
				beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, value));
			}
		}
	}
	
}

public class BeanFactoryTest {
	
	@Test
	public void test() throws Exception{
		// 1.读取配置
		XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(new ResourceLoader());
		xmlBeanDefinitionReader.loadBeanDefinitions("tinyioc.xml");
		
		// 2.初始化BeanFactory并注册bean
		BeanFactory beanFactory = new AutowireCapableBeanFactory();
		for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : xmlBeanDefinitionReader.getRegistry().entrySet()) 
			beanFactory.registerBeanDefinition(beanDefinitionEntry.getKey(), beanDefinitionEntry.getValue());
		
		// 3. 获取bean
		HelloWorldService helloWorldService = (HelloWorldService) beanFactory.getBean("helloWorldService");
		helloWorldService.helloWorld();
	}
}

tinyioc.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
	http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
	http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <bean name="helloWorldService" class="step4.test.HelloWorldService">
        <property name="text" value="Hello World! from step4!"></property>
    </bean>

</beans>



Spring初始化 - AbstractBeanDefinitionReader, XmlBeanDefinitionReader

一.概述
  • lipinganq
  • lipinganq
  • 2017年06月30日 15:11
  • 237

XmlBeanDefinitionReader-----Spring源码解析 配置文件装载与解析

以下内容有部分摘自网络 步骤A. 读取 Resource 文件形成 Document 模型     类图: XmlBeanFactory -> XmlBeanDefinitionRea...
  • Anglebeat
  • Anglebeat
  • 2014年04月18日 11:23
  • 3603

【Spring4揭秘 基础5】BeanDefinition及读取、注册

一、 BeanDefinition及其实现类BeanDefinition接口这个接口描述bean的结构,对应XML中的< bean >或者配置类中的@Bean 它集成了BeanMetadataEl...
  • u011179993
  • u011179993
  • 2016年06月06日 21:59
  • 6265

理解spring的BeanDefinition和配置文件(原文标题:动态注册bean到spring容器)

拷贝地址:http://coolex.info/blog/253.html。 原先的设计是通过已有的库,将数据通过rmi写入到远程服务器;现在有需求需要将支持多个,而且是自定义的远程服务器ip...
  • u012665780
  • u012665780
  • 2014年01月16日 17:59
  • 1672

spring在代码中获取bean的方式

方法一:在初始化时保存ApplicationContext对象  方法二:通过spring提供的utils类获取ApplicationContext对象  方法三:继承自抽象类ApplicationO...
  • long316
  • long316
  • 2016年07月04日 15:07
  • 2510

spring手动注册bean,移除bean,获取bean

注意applicationContext.xml文件的路径配置,按自己项目spring配置文件的路径做相应的调整import org.springframework.beans.factory.con...
  • zhaozhirongfree1111
  • zhaozhirongfree1111
  • 2017年06月09日 16:11
  • 2001

Spring RootBeanDefinition,ChildBeanDefinition,GenericBeanDefinition

RootBeanDefinition,ChildBeanDefinition,GenericBeanDefinition均继承了AbstractBeanDefiniton,其中BeanDefiniti...
  • Truong
  • Truong
  • 2014年06月02日 08:08
  • 4501

41. Spring Boot 使用Java代码创建Bean并注册到Spring中【从零开始学Spring Boot】

已经好久没有讲一些基础的知识了,这一小节来点简单的,这也是为下节的在Spring多数Boot中使用多数据源做准备。 从Spring 3.0开始,增加了一种新的途径来配置Bean Definition,...
  • linxingliang
  • linxingliang
  • 2016年08月26日 08:44
  • 3272

spring技术内幕笔记:IoC容器的初始化过程(3)- BeanDefinition的注册

DefaultListableBeanFactory中,通过一个HashMap来持有和载入BeanDefinition,解析得到的BeanDefinition向IoC容器的beanDefinition...
  • lom9357bye
  • lom9357bye
  • 2017年07月15日 09:01
  • 235

Spring 3.2 源码解析 -- XML bean 元素到 BeanDefinition 解析过程

大体过程: XML 的 ---> Document. element ---> GenericBeanDefinition ---> AbstractBeanDefinition impleme...
  • roszhaodan481
  • roszhaodan481
  • 2014年05月22日 01:29
  • 580
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Spring核心学习(4)从XML中读取BeanDefinition-将代码变成配置
举报原因:
原因补充:

(最多只允许输入30个字)