那些年

在慢慢爬的程序员

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>



阅读更多
个人分类: 框架
上一篇LeetCode Path Sum II
下一篇Spring核心学习(5)将Bean注入Bean-解析依赖
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭