`
零度弥合
  • 浏览: 19185 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
社区版块
存档分类
最新评论

简单模拟实现spring的ioc

 
阅读更多

30岁终于看过JDOM代码了,挺开心的。

 

感谢北风网的spring视频,这个讲师挺平和的,该讲的知识点都讲到了。

http://wenku.baidu.com/course/study/698fa200a6c30c2259019e96

 

同时觉得这是java反射的最好例子,所以写在这里。

 

spring的所谓的注入依赖,控制反转(ioc)我感觉可以简单的理解为把创建对象这工作,交给spring,程序员在xml文件中或注解中指明信息就可以。

 

IOC有三种实现方式

1.通过set方法注入

2.通过构造函数注入

3.使用注解注入

 

这里简单演示一下同过set方法注入。

 

classPath下有一个bean.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans>
	<bean id="studentsDao" class="dao.ipml.StudentsDaoImpl"/>
	<bean id="studentsService" class="service.StudentService">
		<property name="studentsDao" bean="studentsDao"/>
	</bean>
</beans>

 

这其中第一个bean,作为属性注入到第二个bean中,不用被名字迷惑,只是简单总结一下而已。

第一个bean的接口:

package dao;

public interface StudentsDao {
	public void saveStudents();
}

 实现类:

package dao.ipml;

import dao.StudentsDao;

public class StudentsDaoImpl implements StudentsDao {

	@Override
	public void saveStudents() {
		System.out.println("保存成功!!!!");
	}

}

 

被注入的类

package service;

import dao.StudentsDao;

public class StudentService {
	private StudentsDao studentsDao;

	public StudentsDao getStudentsDao() {
		return studentsDao;
	}

	public void setStudentsDao(StudentsDao studentsDao) {
		this.studentsDao = studentsDao;
	}

	public void saveStudents() {
		studentsDao.saveStudents();
	}
}

 

下面就是模拟srping依赖注入的类

package mySrping;

import java.lang.reflect.Method;
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;

public class ClassPathXmlApplicationContext implements BeanFactory {

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

	public ClassPathXmlApplicationContext(String xml) throws Exception {
		SAXBuilder sb = new SAXBuilder();
		// 构造文档对象
		Document doc = sb.build(this.getClass().getClassLoader()
				.getResourceAsStream("beans.xml"));
		// 获取根元素ID
		Element root = doc.getRootElement();
		// 获取此根元素的所有子元素
		List list = (List) root.getChildren("bean");
		for (int i = 0; i < list.size(); i++) {
			Element e = (Element) list.get(i);
			String id = e.getAttributeValue("id");
			String clazz = e.getAttributeValue("class");
			Object o = Class.forName(clazz).newInstance();
			beans.put(id, o);
			for (Element pe : (List<Element>) e.getChildren("property")) {
				String name = pe.getAttributeValue("name");
				String bean = pe.getAttributeValue("bean");
				Object beanObject = beans.get(bean);
				String methodName = "set" + name.substring(0, 1).toUpperCase()
						+ name.substring(1);
				Method method = o.getClass().getMethod(methodName,
						beanObject.getClass().getInterfaces()[0]);
				method.invoke(o, beanObject);
			}
		}
	}

	@Override
	public Object getBean(String id) {
		return beans.get(id);
	}

}

 

测试类是这样的:

package testService;

import service.StudentService;
import mySrping.BeanFactory;
import mySrping.ClassPathXmlApplicationContext;
import junit.framework.TestCase;

public class TestStudentsService extends TestCase {
	public void testSaveStudents() throws Exception {
		BeanFactory beanFactory = new ClassPathXmlApplicationContext(
				"beans.xml");
		StudentService ss = (StudentService) beanFactory
				.getBean("studentsService");
		ss.saveStudents();
	}
}

 

java反射是什么,我感觉最原始的解释是,java可以在知道类名的情况下通过Class.forName(clazz).newInstance();直接得到实例,然后调用其方法。

反射的关键作用是,它是在运行时装配的,而在类中并没有关联。怎么实现呢?就下面这两行代码。

最难理解的是这两句代码

Method method = o.getClass().getMethod(methodName,beanObject.getClass().getInterfaces()[0]);
method.invoke(o, beanObject);

 

o是一个对象,它通过Class.forName(clazz).newInstance();来的到

.getClass()可以获得实例的类型类

.getMethod()可以获得这个类的方法,两个参数第一个是方法名,第二个事参数类型,这里只有一个参数也就是注入bean的第一个接口

 

第二句就是执行这个方法

第一个参数是哪个对象来执行这个方法

第二个参数是执行这个方法需要的参数

 

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics