Spring IOC的简单实现
简单的说,Spring就是通过工厂+反射将我们的bean放到它的容器中的,当我们想用某个bean的时候,只需要调用getBean("beanID")方法即可。
原理简单说明:
Spring容器的原理,其实就是通过解析xml文件,通过反射创建出我们所需要的bean,再将这些bean挨个放到集合中,然后对外提供一个getBean()方法,以便我们获得这bean。
下面我们来简单实现一个demo
beans.xml
- <?xml version="1.0" encoding="UTF-8"?>
 - <beans>
 - <bean id="user" class="com.yyb.model.User" />
 - <bean id="userDAO" class="com.yyb.dao.impl.UserDAOImpl" />
 - <bean id="userService" class="com.yyb.service.UserService">
 - <property name="userDAO" bean="userDAO" />
 - </bean>
 - </beans>
 
BeanFactory
- public interface BeanFactory {
 - Object getBean(String name);
 - }
 
ClassPathXmlApplicationContext:读取xml文件内容,并创建对象及对象关系(使用setter方式)
- package com.yyb.spring;
 - import java.io.IOException;
 - import java.lang.reflect.InvocationTargetException;
 - 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.JDOMException;
 - import org.jdom.input.SAXBuilder;
 - public class ClassPathXmlApplicationContext implements BeanFactory
 - {
 - private Map<String, Object> beans = new HashMap<String, Object>();
 - public ClassPathXmlApplicationContext() throws JDOMException, IOException,
 - InstantiationException, IllegalAccessException,
 - ClassNotFoundException, SecurityException, NoSuchMethodException,
 - IllegalArgumentException, InvocationTargetException
 - {
 - SAXBuilder sb = new SAXBuilder();
 - // 构造文档对象
 - Document doc = sb.build(ClassPathXmlApplicationContext.class
 - .getClassLoader().getResourceAsStream("beans.xml"));
 - // 获取根元素
 - Element root = doc.getRootElement();
 - // 取到根元素所有元素
 - List list = root.getChildren();
 - for (int i = 0; i < list.size(); i++)
 - {
 - Element element = (Element) list.get(i);
 - // 取id子元素
 - String beanid = element.getAttributeValue("id");
 - // 取class子元素
 - String clzss = element.getAttributeValue("class");
 - // 实例化
 - Object o = Class.forName(clzss).newInstance();
 - // 将所有bean放入map中
 - beans.put(beanid, o);
 - // 获取property 进行依赖注入
 - for (Element propertyElement : (List<Element>) element
 - .getChildren("property"))
 - {
 - String name = propertyElement.getAttributeValue("name");
 - System.out.println(name);//userDAO
 - String bean = propertyElement.getAttributeValue("bean");
 - System.out.println(bean);//userDAO
 - // 从beans.xml中根据id取到类的对象
 - //Object beanObj = this.getBean(name);
 - // 从beans.xml中根据id取到类的对象
 - Object beanObj = this.getBean(bean);
 - System.out.println(beanObj);//com.yyb.dao.impl.UserDAOImpl@a09ee92
 - // 形成setXXX方法名
 - String methodName = "set" + name.substring(0, 1).toUpperCase()
 - + name.substring(1);
 - System.out.println(name.substring(0, 1).toUpperCase());//U
 - System.out.println(name.substring(1));//serDAO
 - System.out.println(methodName);//setUserDAO
 - // 反射机制对方法进行调用,将对象在加载bean时就注入到环境上下文中
 - Method m = o.getClass().getMethod(methodName,
 - beanObj.getClass().getInterfaces()[0]);
 - System.out.println(o.getClass());//class com.yyb.service.UserService
 - System.out.println(beanObj.getClass().getInterfaces()[0]);//interface com.yyb.dao.UserDAO
 - System.out.println(m);//public void com.yyb.service.UserService.setUserDAO(com.yyb.dao.UserDAO)
 - // 执行注入,相当于执行了一个setXXX(args..)的方法
 - m.invoke(o, beanObj);
 - }
 - }
 - }
 - @Override
 - public Object getBean(String name)
 - {
 - return beans.get(name);
 - }
 - }
 
对于以上这段代码实现的效果为:
Service service=(Service)beans.get("userService");
Dao dao = (Dao)beans.get("userDAO");
//依赖注入,Service实现依赖dao的实现
service.setDao(dao);
User:实体类
- public class User {
 - private String userName;
 - private String password;
 - /**
 - * @return the userName
 - */
 - public String getUserName()
 - {
 - return userName;
 - }
 - /**
 - * @param userName
 - * the userName to set
 - */
 - public void setUserName(String userName)
 - {
 - this.userName = userName;
 - }
 - /**
 - * @return the password
 - */
 - public String getPassword()
 - {
 - return password;
 - }
 - /**
 - * @param password
 - * the password to set
 - */
 - public void setPassword(String password)
 - {
 - this.password = password;
 - }
 - public String toString()
 - {
 - StringBuffer sb = new StringBuffer();
 - sb.append(this.userName);
 - sb.append(this.password);
 - return sb.toString();
 - }
 - }
 
UserDAO
- public interface UserDAO {
 - void save(User u);
 - void delete();
 - }
 
UserDAOImpl
- public class UserDAOImpl implements UserDAO {
 - @Override
 - public void save(User u) {
 - System.out.println("User:" + u.toString());
 - }
 - @Override
 - public void delete() {
 - System.out.println("delete User");
 - }
 - }
 
UserService
- public class UserService {
 - private UserDAO userDAO;
 - public void addUser(User u)
 - {
 - this.userDAO.save(u);
 - }
 - /**
 - * @return the userDAO
 - */
 - public UserDAO getUserDAO()
 - {
 - return userDAO;
 - }
 - /**
 - * @param userDAO
 - * the userDAO to set
 - */
 - public void setUserDAO(UserDAO userDAO)
 - {
 - this.userDAO = userDAO;
 - }
 - }
 
下面我们来简单测试一下实现的效果:
Client
- public class client {
 - public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException, JDOMException, IOException {
 - BeanFactory factory = new ClassPathXmlApplicationContext();
 - //通过工厂直接获取
 - UserService userService = (UserService) factory.getBean("userService");
 - //其实User也可以从工厂中获得
 - User u=(User)factory.getBean("user");
 - //User u = new User();
 - u.setUserName("yyb");
 - u.setPassword("1234");
 - userService.addUser(u);//打印结果yyb1234
 - }
 - }
 
当然以上我们是通过setter方法注入,还可以使用构造器注入,也就是在建立对象的时候建立关系(即在UserService的构造函数中添加对userDAO的赋值操作)
总结:
以上通过IOC的一个简要实现实例,模拟了Spring中IOC的实现,虽然只是完成了Spring中依赖注入的一小部分工作,但是很好的展现了Java反射机制在Spring中的应用,能使我们能更好的从原理上了解IOC的实现,也能为我们实现自己的Spring框架提供了方案。
Spring IOC实现原理demo:IOC
                    
                
                
            
        
浙公网安备 33010602011771号