文件夹

     【SSH进阶之路】一步步重构容器实现Spring框架——从一个简单的容器開始(八)

     【SSH进阶之路】一步步重构容器实现Spring框架——解决容器对组件的“侵入式”管理的两种方案--主动查找和控制反转(九)

     【SSH进阶之路】一步步重构容器实现Spring框架——配置文件+反射实现IoC容器(十)

     【SSH进阶之路】一步步重构容器实现Spring框架——彻底封装,实现简单灵活的Spring框架(十一)

博文【SSH进阶之路】一步步重构容器实现Spring框架——从一个简单的容器開始(八),我们为了去掉接口对详细实现的依赖关系,封装了一个特别简陋的容器。

      博文【SSH进阶之路】一步步重构容器实现Spring框架——解决容器对组件的“侵入式”管理的两种方案--主动查找和控制反转(九),我们利用控制反转,去掉了组件对容器的依赖。

博文【SSH进阶之路】一步步重构容器实现Spring框架——配置文件+反射实现IoC容器(十),我们实现了读取配置文件,以及容器创建对象的灵活,简单的IoC。

这篇博文的目标是不仅形似Spring,并且要神似Spring,进一步封装对象的依赖关系。

我们知道Spring框架,不仅能够依据配置创建对象,并且能够依据配置创建对象之间的依赖关系。对象之间的依

赖关系怎么配置呢,那我们先看一下配置文件。

<?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">
<property name="dao" ref="dao"></property>
</bean> </beans>

我们发现配置文件里多了两个属性:property和ref,表达了Service须要依赖Dao的关系,所以我们须要将dao注入

给Service,怎么做呢?我们仅仅须要像存储bean一样建立一个JavaBean就可以:

public class PropertyDefinition {

	private String name;
private String ref; public PropertyDefinition(String name, String ref) {
this.name = name;
this.ref = ref;
} public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRef() {
return ref;
}
public void setRef(String ref) {
this.ref = ref;
} }

有了javabean,我们就仅仅须要专注于怎么为bean对象的属性注入值。我们能够利用内省来操作Bean类属性、事

件。一般的做法是通过类Introspector来获取某个对象的BeanInfo信息,然后通过BeanInfo来获取属性的描写叙述器

(PropertyDescriptor),通过这个属性描写叙述器就能够获取某个属性相应的getter/setter方法,然后我们就能够通过反

射机制来调用这些方法,最后将引用对象注入到属性中。

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
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; /**
* 容器
*
* @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() {
for (BeanDefinition beanDefinition :beanDefines) {
Object bean = sigletons.get(beanDefinition.getId());
if(bean != null){
try {
// 通过Introspector取得bean的定义信息,之后再取得属性的描写叙述信息,返回一个数组
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); for(PropertyDefinition propertyDefinition:beanDefinition.getPropertys()){
for(PropertyDescriptor properdesc: ps){
if(propertyDefinition.getName().equals(properdesc.getName())){
// 获取属性的setter方法,private
Method setter = properdesc.getWriteMethod();
if(setter != null){
Object value = sigletons.get(propertyDefinition.getRef());
// 同意訪问私有方法
setter.setAccessible(true);
// 把引用对象注入到属性
setter.invoke(bean, value);
}
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
} /**
* 完毕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++) {
// 将根元素beans下的bean子元素作为一个新的子根元素
Element elementBean = (Element) listBean.get(i);
//获取id属性值
String id = elementBean.getAttributeValue("id");
//获取class属性值
String clazz = elementBean.getAttributeValue("class"); BeanDefinition beanDefine = new BeanDefinition(id,clazz);
// 获取子根元素bean下的全部property子元素
List listProperty = elementBean.getChildren("property");
// 遍历子根元素的子元素集合(即遍历property元素)
for (int j = 0; j < listProperty.size(); j++) {
// 获取property元素
Element elmentProperty = (Element)listProperty.get(j);
// 获取name属性值
String propertyName = elmentProperty.getAttributeValue("name");
// 获取ref属性值
String propertyref = elmentProperty.getAttributeValue("ref"); PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName,propertyref); beanDefine.getPropertys().add(propertyDefinition);
} // 将javabean加入到集合中
beanDefines.add(beanDefine);
}
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 获取bean实例
*/
@Override
public Object getBean(String beanName) {
return this.sigletons.get(beanName);
}
}

此时我们就能够把Service接口的set方法去掉了。

public interface Service {
public void serviceMethod();
}

这里仅有部分代码,大家能够在以下链接中下载。

 

总结

经过四篇博文的重构,我们实现了一个Spring的雏形,它能够让我们更加深刻的认识Spring的原理,对我们更加

深入的学习Spring埋下了伏笔。

源代码下载

【SSH进阶之路】一步步重构容器实现Spring框架——彻底封装,实现简单灵活的Spring框架(十一)的更多相关文章

  1. 【SSH进阶之路】Struts + Spring + Hibernate 进阶开端(一)

    [SSH进阶之路]Struts + Spring + Hibernate 进阶开端(一) 标签: hibernatespringstrutsssh开源框架 2014-08-29 07:56 9229人 ...

  2. 【SSH进阶之路】Spring的IOC逐层深入——为什么要使用IOC[实例讲解](二)

    上篇博客[SSH进阶之路]Spring简介,搭建Spring环境——轻量级容器框架(一),我们简单的介绍了Spring的基本概念,并且搭建了两个版本的Spring开发环境,但是我们剩下了Spring最 ...

  3. 【SSH进阶之路】Hibernate映射——多对一单向关联映射(四)

    [SSH进阶之路]Hibernate基本原理(一) ,小编介绍了Hibernate的基本原理以及它的核心,採用对象化的思维操作关系型数据库. [SSH进阶之路]Hibernate搭建开发环境+简单实例 ...

  4. 【SSH进阶之路】Hibernate映射——一对一双向关联映射(六)

    上篇博文[SSH进阶之路]Hibernate映射--一对一单向关联映射(五),我们介绍了一对一的单向关联映射,单向是指仅仅能从人(Person)这端载入身份证端(IdCard),可是反过来.不能从身份 ...

  5. 【SSH进阶之路】Hibernate基本映射(三)

    [SSH进阶之路]Hibernate基本原理(一) ,小编介绍了Hibernate的基本原理以及它的核心.採用对象化的思维操作关系型数据库. [SSH进阶之路]Hibernate搭建开发环境+简单实例 ...

  6. SSH进阶之路

    [SSH进阶之路]Hibernate基本原理(一)       在开始学Hibernate之前,一直就有人说:Hibernate并不难,无非是对JDBC进一步封装.一句不难,难道是真的不难还是眼高手低 ...

  7. 【SSH进阶之路】Hibernate映射——一对一单向关联映射(五)

    [SSH进阶之路]Hibernate基本原理(一) ,小编介绍了Hibernate的基本原理以及它的核心,採用对象化的思维操作关系型数据库. [SSH进阶之路]Hibernate搭建开发环境+简单实例 ...

  8. 【SSH进阶之路】Hibernate搭建开发环境+简单实例(二)

    Hibernate是很典型的持久层框架,持久化的思想是很值得我们学习和研究的.这篇博文,我们主要以实例的形式学习Hibernate,不深究Hibernate的思想和原理,否则,一味追求,苦学思想和原理 ...

  9. 【SSH进阶之路】Hibernate系列——总结篇(九)

    这篇博文是Hibernate系列的最后一篇,既然是最后一篇,我们就应该进行一下从头到尾,整体上的总结,将这个系列的内容融会贯通. 概念 Hibernate是一个对象关系映射框架,当然从分层的角度看,我 ...

随机推荐

  1. cocos2dx手写js绑定C++

    这两天连续查阅了js绑定c++的非常多文章  , 有手动与自己主动两种方式 . 本来想用自己主动绑定的 , 可是NDK一直下载不下来.....就给算了 . 以下总结一下手动绑定的实现过程 : 一共三步 ...

  2. Java算法分析1—————寻找数组同样元素

    算法的两个评測指标:执行时间和内存消耗 要么用时间换空间,要么用空间换时间 寻找数组同样元素測试一: 0~99共100个元素各不同样,新增加一个0~99的元素不明白位置 从101个元素数组中找出与0~ ...

  3. oracle database 12c R1 安装文档

    INSTALLORACLE DATABASE 12C 完整的安装文档下载地址: http://download.csdn.net/detail/royjj/5665869 OS:ORALCE LINU ...

  4. C#之再议数组和集合

    1.数组 1.1简单数组 1.2 多维数组 1.3锯齿数组 1.4Array数组 1.5作为参数的数组 1.6枚举 1.7结构 以上部分可参考 http://www.cnblogs.com/ztb12 ...

  5. C#获取设备的IP和Mac类

    /// <summary> /// 此类用于获得设备的Ip和Mac /// </summary> public class Mac { [DllImport("Iph ...

  6. Android-Universal-Image-Loader学习笔记(一个)

    Android-Universal-Image-Loader它是一个开源项目,处理图像加载和缓存.闲暇的时候,读一些源.特别记录. 所述图像文件(磁盘)高速缓存,我们需要考虑的因素,如以下 1)  定 ...

  7. HTTPDNS成为移动互联网的标配–原因与原理解析(转)

    DNS,作用就是将域名解析成IP.一个DNS查询,先从本地缓存查找,如果没有或者已经过期,就从DNS服务器查询,如果客户端没有主动设置DNS服务器,一般是从服务商DNS服务器上查找.这就出现了不可控. ...

  8. 京东评论情感分类器(基于bag-of-words模型)

    京东评论情感分类器(基于bag-of-words模型) 近期在本来在研究paraVector模型,想拿bag-of-words来做对照. 数据集是京东的评论,经过人工挑选,选出一批正面和负面的评论. ...

  9. Windows Phone开发(16):样式和控件模板

    原文:Windows Phone开发(16):样式和控件模板 在前面资源一文中也提过样式,样式就如同我们做HTML页排版时常用到的CSS样式表,它是对于特定娄型的可视化元素,应该可以直接说是针对控件的 ...

  10. Google Map API V2密钥申请

    之前用的都是v1,用的是MapView,好吧,仅仅能认命了.废话不再多说,開始android 的Google Maps Android API v2吧 之前參考了http://www.cnblogs. ...