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

一步步重构容器实现Spring框架——配置文件+反射实现IoC容器(十)

2018-01-13 00:00 429 查看
上篇博文容器初始化时,使用new的方式来实力化对象,这篇博文我们利用配置文件+反射实力化对象,进一步封

装降低容器和组件的耦合度。下面我们先看一下配置文件。

[html] view plain copy

<?xml version="1.0" encoding="UTF-8"?>

<beans>

<bean id="dao" class="com.tgb.container.dao.impl.Dao4MySqlImpl" />

<bean id="service" class="com.tgb.container.service.impl.ServiceImpl" />

</beans>

看到上面的配置文件,除了命名空间没有,和Spring的配置文件已经很像了,下面我们就使用dom4j或jdom来读取

配置文件,并将配置文件中配置类利用反射实例化。本实例我们使用的jdom,大家也可以使用dom4j试一下。下面我

们看一下读取配置文件的代码:

[java] view plain copy

public interface BeanFactory {

Object getBean(String id);

}

[java] view plain copy

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import org.jdom.Document;

import org.jdom.Element;

import org.jdom.input.SAXBuilder;

import org.jdom.xpath.XPath;

import com.tgb.container.dao.Dao;

import com.tgb.container.service.Service;

/**

* 从类路径加载配置文件

*

* @author liang

*

*/

public class ClassPathXmlApplicationContext implements BeanFactory {

// 用于存放Bean

private Map<String, Object> beans = new HashMap<String, Object>();

public ClassPathXmlApplicationContext(String fileName) {

this.readXML(fileName);

}

// 解析xml文件,通过反射将配置的beasn放到container中,并实现依赖注入

private void readXML(String fileName) {

// 创建SAXBuilder对象

SAXBuilder saxBuilder = new SAXBuilder();

// 读取资源,获得document对象

Document doc;

try {

doc = saxBuilder.build(this.getClass().getClassLoader().getResourceAsStream(fileName));

// 获取根元素

Element rootEle = doc.getRootElement();

// 从根元素获得所有的子元素,建立元素集合

List listBean = XPath.selectNodes(rootEle, "/beans/bean");

// 遍历根元素的子元素集合,扫描配置文件中的bean

for (int i = 0; i < listBean.size(); i++) {

Element bean = (Element) listBean.get(i);

// 获取id属性值

String id = bean.getAttributeValue("id");

// 获取class属性值

String clazz = bean.getAttributeValue("class");

// 反射,实例化

Object o = Class.forName(clazz).newInstance();

beans.put(id, o);

}

// 依赖管理,这里还不灵活,但是原理是一样的

Service service = (Service) beans.get("service");

Dao dao = (Dao) beans.get("dao");

// 依赖注入,Service实现依赖dao的实现

service.setDao(dao);

} catch (Exception e) {

e.printStackTrace();

}

}

/**

* 查找组件

*

* @param id

* @return

*/

@Override

public Object getBean(String id) {

return beans.get(id);

}

}

看到上面的代码,我们发现读取配置文件的方法中包含了反射,代码的可读性太差,并且对面向对象的封装不够彻

底,下面我们将bean的实例化以及依赖注入进行进一步的封装。

封装bean的实例化

为了做进一步的封装,我们将配置文件的属性封装成一个javabean,为了存放我们的属性值。如下所示:

[java] view plain copy

public class BeanDefinition {

private String id;

private String className;

public BeanDefinition(String id, String className) {

this.id = id;

this.className = className;

}

public String getId() {

return id;

}

public void setId(String id) {

this.id = id;

}

public String getClassName() {

return className;

}

public void setClassName(String className) {

this.className = className;

}

}

现在我们就可以把bean的实例化做进一步的封装了。

[java] view plain copy

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import org.jdom.Document;

import org.jdom.Element;

import org.jdom.input.SAXBuilder;

import org.jdom.xpath.XPath;

import com.tgb.container.dao.Dao;

import com.tgb.container.service.Service;

/**

* 容器

*

* @author liang

*

*/

public class ClassPathXmlApplicationContext implements BeanFactory {

// 用于存放Bean

private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();

// 用于存放Bean的实例

private Map<String, Object> sigletons =new HashMap<String, Object>();

public ClassPathXmlApplicationContext(String fileName) {

this.readXML(fileName);

this.instanceBeans();

this.injectObject();

}

/**

* 依赖注入,为bean对象的属性注入值

* 这里还不灵活,但是原理是一样的

*/

private void injectObject() {

Service service = (Service) this.sigletons.get("service");

Dao dao = (Dao) this.sigletons.get("dao");

//依赖注入,Service实现依赖dao的实现

service.setDao(dao);

}

/**

* 完成bean的实例化

*/

private void instanceBeans() {

for(BeanDefinition beanDefinition : beanDefines){

try {

if(beanDefinition.getClassName() != null && !"".equals(beanDefinition.getClassName().trim())){

sigletons.put(beanDefinition.getId(),Class.forName(beanDefinition.getClassName()).newInstance() );

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

/**

* 读取xml配置文件

*/

private void readXML(String fileName) {

// 创建SAXBuilder对象

SAXBuilder saxBuilder = new SAXBuilder();

try {

// 读取资源,获得document对象

Document doc = saxBuilder.build(this.getClass().getClassLoader()

.getResourceAsStream(fileName));

// 获取根元素

Element rootEle = doc.getRootElement();

// 从根元素获得所有的子元素,建立元素集合

List listBean = XPath.selectNodes(rootEle, "/beans/bean");

// 遍历根元素的子元素集合,扫描配置文件中的bean

for (int i = 0; i < listBean.size(); i++) {

Element bean = (Element) listBean.get(i);

// 获取id属性值

String id = bean.getAttributeValue("id");

// 获取class属性值

String clazz = bean.getAttributeValue("class");

BeanDefinition beanDefine = new BeanDefinition(id,clazz);

// 将javabean添加到集合中

beanDefines.add(beanDefine);

}

} catch (Exception e) {

e.printStackTrace();

}

}

/**

* 获取bean实例

*/

@Override

public Object getBean(String beanName) {

return this.sigletons.get(beanName);

}

}

我们知道容器不仅负责创建对象,而且可以管理对象的依赖关系,管理对象的生命周期等等。我们仅实现了容器

灵活创建对象的部分,依赖注入部分是由我们手动注入的。 对象的依赖关系还不灵活,但是我们已经能够看到IoC的

影子了,只是形似,还没有达到神似的目标。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Spring
相关文章推荐