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

前导:开始学习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>
时间: 2024-10-12 17:34:08

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

Spring核心学习(1)实现基本的容器-包括注入和获取功能

前导:开始学习Spring核心思想,通过一个山寨精简版Spriing代码结合学习. 内容:1. BeanDefinition-保存Bean及配置信息 2. BeanFactory-对Bean进行管理. BeanDefinition: public class BeanDefinition { private Object bean; public BeanDefinition(Object object) { this.bean = object; } public Object getBean

Spring核心学习(2)管理Bean的生命周期

前导:开始学习Spring核心思想,通过一个山寨精简版Spriing代码结合学习. 内容:1. 抽象BeanFactory-面向接口更易拓展BeanFactory-面向接口更易拓展. 2. 在AbstractBeanFactory内部初始化Bean. 这里的BeanDefinition相比上一个更加丰富,多了BeanDefinition包含的Bean的Class的信息,这里我们不在注册前就把Bean实例化给BeanDefinition,而是延迟到注册的时候才实例化Bean给BeanDefinit

Spring核心学习(5)将Bean注入Bean-解析依赖

前导:开始学习Spring核心思想,通过一个山寨精简版Spring代码结合学习. 内容:1. BeanReference-保存Bean的引用. 2. getBean()中调用createBean()-lazy-init.这次我们用到了在Bean中注入Bean的情况,在这里我们再一次改写了AbstractBeanFactory,改写后的AbstractBeanFactory将多出一个List来保存所有注册的对象名,而且我们不再是注册时候就创建bean,并将beanDefinition的bean注入

Spring核心学习(6)引用ApplicationContext-包装Bean的初始化过程,对应用透明

前导:开始学习Spring核心思想,通过一个山寨精简版Spring代码结合学习. 这是IOC的最终版本,在这里我们将BeanFactory包装了起来,让流程能真正的像Spring那样简单.我们新定义了一个接口去继承BeanFactory,然后通过组合的方式将AbstractBeanFactory添加进来,最后的ClassPathXmlApplicationContext类将真正的把Bean的建立,组装都完成. IOC的收获:框架开发思想:在代码实现中,配置和逻辑要有明确的分水岭:1. XML=>

Spring核心学习(3)为Bean注入属性

前导:开始学习Spring核心思想,通过一个山寨精简版Spring代码结合学习. 内容:1.Propertyvalue-保存属性注入信息.2.AutowireCapableBeanFactory-可自动装配的BeanFactory. 这里我们重新定义了BeanDefinition,增加了属性列表这个字段,我们将为bean附加额外的属性,所以我们又定了PropertyValues.PropertyValue来辅助,当我们为bean定义的时候同时设置他的属性,通过反射机制来动态的附加到bean里,来

Spring核心学习-AOP(7) 织入和代理

前导:开始学习Spring核心思想,通过一个山寨精简版Spring代码结合学习. AdvisedSupport - 保存AOP配置 TargetSource - 保存被代理的数据 AopProxy - 对代理对象做代理,在调用目标方法前先调用它. JdkDynamicAopProxy - 使用JDK动态代理对接口做代理 ReflectiveMethodInvocation - 将反射的Method封装为Joinpoint MethodInterceptor - 对方法调用连接点实现包围通知的 A

spring的配置文件在web.xml中加载的方式

web.xml加载spring配置文件的方式主要依据该配置文件的名称和存放的位置不同来区别,目前主要有两种方式. 1.如果spring配置文件的名称为applicationContext.xml,并且存放在WEB-INF/目录下,那么只需要在web.xml中加入以下代码即可 <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> &

【学习】从.txt文件读取生成编译代码。

1 string code = null; 2 String projectName = Assembly.GetExecutingAssembly().GetName().Name; 3 // 1. 生成要编译的代码.(示例为了简单直接从程序集内的资源中读取) 4 Stream stram = Assembly.GetExecutingAssembly() 5 .GetManifestResourceStream(projectName + ".code.txt"); 6 using

Java学习-023-Properties 类 XML 配置文件读取及写入源代码

之前的几篇 Properties 文章已经讲述过了 Java 配置文件类 Properties 的基本用法,查看 JDK 的帮助文档时,也可看到在 Properties 类中还有两个方法 loadFromXML(InputStream) 和 storeToXml(OutputStream, String, String),由方法名中的 xml 不难确定这两个方法分别是读取/写入数据到 xml 文件.JDK 文档部分如下所示: 因而此文将通过源码实例演示 Properties 类是如何将数据写入