这两天想好好学习一下spring,对于spring的东西无非就是一些配置,但是不想只停留在应用的层面。一直以来对spring的内部的运行的原理非常好奇,想着研究一下源码,但是把源码拿过来如大海捞针,实在是无从下手,于是乎,自己综合查了的一些资料实现了spring式的IOC,感觉很有意思。下边把代码贴出来:
首先是定义了两个测试用的接口:
package com.ioc.dao;
public interface Car {
void cleanCar();
}
package com.ioc.dao;
public interface CarService {
void sell();
}
和两个接口的实现:
package com.ioc.dao.impl;
import com.ioc.dao.Car;
public class CarImpl implements Car {
@Override
public void cleanCar() {
System.out.println("正在进行洗车!");
}
}
package com.ioc.dao.impl;
import com.ioc.dao.Car;
import com.ioc.dao.CarService;
public class CarServiceImpl implements CarService {
private Car car;
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
@Override
public void sell() {
car.cleanCar();
}
}
以上四个类或者是接口用于测试,主要是验证依赖注入
BeanObject这个类用于处理xml文件中bean的对象,List集合用于接收属性
package com.ioc.realize;
import java.util.ArrayList;
import java.util.List;
/**
* 对应于xml文件中的
* <bean id="car" class="com.ioc.dao.impl.CarImpl"></bean>
* Copyright 2015年10月27日
* created by txxs
* all right reserved
*/
public class BeanObject {
private String id;
private String className;
//属性集合
private List<AttributeObject> propertys = new ArrayList<AttributeObject>();
public BeanObject(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;
}
public List<AttributeObject> getPropertys() {
return propertys;
}
public void setPropertys(List<AttributeObject> propertys) {
this.propertys = propertys;
}
}
AttributeObject这个类用来处理XML中的属性
package com.ioc.realize;
/**
* 存放属性的对象,对应
* <property name="car" ref="car"></property>
* Copyright 2015年10月27日
* created by txxs
* all right reserved
*/
public class AttributeObject {
private String name;
private String ref;
public AttributeObject(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;
}
}
下边就是自己的上下文SelfClassPathXMLApplicationContext,首先读取XML文件,读取完成后建立bean和属性的集合,然后实例化bean,再将依赖的bean注入
package com.ioc.realize;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
public class SelfClassPathXMLApplicationContext {
private List<BeanObject> beanObjects = new ArrayList<BeanObject>();
private Map<String, Object> sigletons = new HashMap<String, Object>();
public SelfClassPathXMLApplicationContext(String filename){
this.readXML(filename);
this.instanceBeans();
this.injectObject();
}
/**
* 为bean对象的属性注入值
*/
private void injectObject() {
for(BeanObject beanObject : beanObjects){
Object bean = sigletons.get(beanObject.getId());
if(bean!=null){
try {
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
for(AttributeObject property : beanObject.getPropertys()){
for(PropertyDescriptor properdesc : ps){
if(property.getName().equals(properdesc.getName())){
Method setter = properdesc.getWriteMethod();//获取属性的setter方法
if(setter!=null){
Object value = sigletons.get(property.getRef());
setter.setAccessible(true);
setter.invoke(bean, value);//把引用对象注入到属性
}
break;
}
}
}
} catch (Exception e) {
}
}
}
}
/**
* 完成bean的实例化
*/
private void instanceBeans() {
for(BeanObject beanObject : beanObjects){
try {
String aa = beanObject.getClassName().trim();
if(beanObject.getClassName()!=null && !"".equals(beanObject.getClassName().trim()))
sigletons.put(beanObject.getId(),Class.forName(beanObject.getClassName()).newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 读取xml配置文件
* @param filename
*/
private void readXML(String filename) {
//创建xml解析对象
SAXReader saxReader = new SAXReader();
Document document=null;
try{
//filename不能以'/'开头时,path是从ClassPath根下获取
URL xmlpath = this.getClass().getClassLoader().getResource(filename);
//读取XML文件,获得document对象
document = saxReader.read(xmlpath);
Map<String,String> nsMap = new HashMap<String,String>();
//加入命名空间
nsMap.put("ns","http://www.yours.org/beans");
//创建beans/bean查询路径
XPath xsub = document.createXPath("//ns:beans/ns:bean");
//设置命名空间
xsub.setNamespaceURIs(nsMap);
//获取文档下所有bean节点
List<Element> beans = xsub.selectNodes(document);
for(Element element: beans){
//获取id属性值
String id = element.attributeValue("id");
//获取class属性值
String clazz = element.attributeValue("class");
BeanObject beanObject = new BeanObject(id, clazz);
XPath propertysub = element.createXPath("ns:property");
//设置命名空间
propertysub.setNamespaceURIs(nsMap);
List<Element> propertys = propertysub.selectNodes(element);
for(Element property : propertys){
String propertyName = property.attributeValue("name");//元素内部引用的属性也获取
String propertyref = property.attributeValue("ref");
AttributeObject attributeObject = new AttributeObject(propertyName, propertyref);
beanObject.getPropertys().add(attributeObject);
}
beanObjects.add(beanObject);
}
}catch(Exception e){
e.printStackTrace();
}
}
/**
* 获取bean实例
* @param beanName
* @return
*/
public Object getBean(String beanName){
return this.sigletons.get(beanName);
}
}
测试类:
package com.ioc.test;
import com.ioc.dao.CarService;
import com.ioc.realize.SelfClassPathXMLApplicationContext;
public class SpringIocTest {
public static void main(String args[]){
SelfClassPathXMLApplicationContext ctx = new SelfClassPathXMLApplicationContext("IocConfig.xml");
CarService carService = (CarService)ctx.getBean("carService");
carService.sell();
}
}
输出结果:
正在进行洗车!
下边是一些资料:
http://uule.iteye.com/blog/2059920
http://dingjun1.iteye.com/blog/210165
http://lgbolgger.iteye.com/category/322988
http://www.iteye.com/topic/1125248