一、前言
IOC (Inverse of control) - 控制反转,spring的IOC实现原理为利用Java的反射机制并充当工厂的角色完成对象的装配和注入。
二、实现细节
附上一张类的结构图,该例子需要导入jdom.jar和junit.jar

< http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+CqLZINPDu6dCZWFuPC9wPgo8cHJlIGNsYXNzPQ=="brush:java;">package com.zdp.model; // 用户类 public class User { private String userName; private String password; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }② UserService
package com.zdp.service;
import com.zdp.dao.UserDao;
import com.zdp.model.User;
public class UserService {
private UserDao userDao;
public void add(User user) {
userDao.save(user);
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
③ UserDao
package com.zdp.dao;
import com.zdp.model.User;
public class UserDao {
public void save(User user) {
System.out.println("user saved!");
}
}
④ Bean工厂接口
package com.zdp.spring;
// Bean工厂接口
public interface BeanFactory {
public Object getBean(String id);
}⑤ Bean工厂实现
package com.zdp.spring;
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;
// Bean工厂实现类
public class ClassPathXmlApplicationContext implements BeanFactory {
private Map
beans = new HashMap
(); public ClassPathXmlApplicationContext() throws Exception { SAXBuilder sb = new SAXBuilder(); Document doc = sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml")); // 构造文档对象 Element root = doc.getRootElement(); // 获取根元素HD List list = root.getChildren("bean"); // 取名字为bean的所有元素 for (int i = 0; i < list.size(); i++) { Element element = (Element) list.get(i); String id = element.getAttributeva lue("id"); String clazz = element.getAttributeva lue("class"); Object beanObj = Class.forName(clazz).newInstance(); // 反射获取对象 beans.put(id, beanObj); // 将对象存入Bean工厂 for (Element propertyElement : (List
) element.getChildren("property")) { String name = propertyElement.getAttributeva lue("name"); // name="userDao" String bean = propertyElement.getAttributeva lue("bean"); // bean="userDao" Object injectObject = beans.get(bean); // 从Bean工厂中获取UserDao String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1); // setUserDao Method method = beanObj.getClass().getMethod(methodName, injectObject.getClass()); method.invoke(beanObj, injectObject); // set注入UserDao对象 } } } public Object getBean(String id) { return beans.get(id); } }
这里为核心代码,当然在实际情况中,这一块要复杂的多, 例如:可以一个bean引用另一个bean,还可以有多个配置文件、通过多种方式载入配置文件等等,不过原理还是采用Java的反射机制。
⑥ 配置文件
⑦ 单元测试
package com.zdp.service;
import org.junit.Test;
import com.zdp.model.User;
import com.zdp.spring.BeanFactory;
import com.zdp.spring.ClassPathXmlApplicationContext;
// 测试代码
public class UserServiceTest {
@Test
public void testAdd() throws Exception {
BeanFactory applicationContext = new ClassPathXmlApplicationContext(); // 获取上下文
UserService service = (UserService) applicationContext.getBean("userService"); // Spring装配Bean
User user = new User();
user.setUserName("zhangsan");
user.setPassword("123456");
service.add(user); // 将user保存入库
}
}
三、小结
上文仅仅是简单地模拟了spring的IOC的实现,虽然只是完成了spring中依赖注入的一小部分,但还是很好地展现了Java反射机制在spring中的应用,对于初学者理解IOC应该会有一点帮助。