首页 > 代码库 > Spring依赖注入 --- 模拟实现

Spring依赖注入 --- 模拟实现

Spring依赖注入 --- 模拟实现

 

 

面向接口编程,又称面向抽象编程,

数据库如果发生更改,对应的数据访问层也应该改变
多写几个实现,需要用谁的时候在service里new谁就可以了
面向抽象编程的好处就是灵活。

 

创建用户实体类,

/ImitateSpring/src/yuki/spring/imitate/pojo/User.java

package yuki.spring.imitate.pojo;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;    }    }

 

/ImitateSpring/src/yuki/spring/imitate/service/UserService.java

package yuki.spring.imitate.service;import yuki.spring.imitate.dao.UserDAO;import yuki.spring.imitate.pojo.User;public class UserService {    private UserDAO userDAO/* = new UserDAOImpl()*/;        public UserDAO getUserDAO() {        return userDAO;    }    public void setUserDAO(UserDAO userDAO) {        this.userDAO = userDAO;    }        public void add(User u){        this.userDAO.save(u);    }}

 

/ImitateSpring/src/yuki/spring/imitate/dao/UserDAO.java

package yuki.spring.imitate.dao;import yuki.spring.imitate.pojo.User;/*public class UserDAO {    public void save(User u){        System.out.println("user saved...");    }}*/public interface UserDAO {    void save(User u);}

 

/ImitateSpring/src/yuki/spring/imitate/dao/impl/UserDAOImpl.java

package yuki.spring.imitate.dao.impl;import yuki.spring.imitate.dao.UserDAO;import yuki.spring.imitate.pojo.User;public class UserDAOImpl implements UserDAO {    @Override    public void save(User u) {        System.out.println("user saved...");    }}

 

之前的new很多DAO的解决方式是写工厂方法
现在,要新建一个总的工厂,把消息写在工厂文件中
用jdom解析xml,反射创建对象

引入jar包,jdom-2.0.5.jar

/ImitateSpring/src/yuki/spring/imitate/xml/test.xml

<?xml version="1.0" encoding="UTF-8"?><HD>    <disk name="C">        <capacity>8G</capacity>        <directories>200</directories>        <files>1580</files>    </disk>    <disk name="D">        <capacity>10G</capacity>        <directories>500</directories>        <files>3000</files>    </disk></HD>

 

/ImitateSpring/src/yuki/spring/imitate/spring/ClassPathXmlApplicationContext.java

package yuki.spring.imitate.xml;import java.util.List;import org.jdom2.Document;import org.jdom2.Element;import org.jdom2.input.SAXBuilder;public class Sample1 {    public static void main(String[] args) throws Exception {        SAXBuilder saxBuilder = new SAXBuilder();        Document document = saxBuilder.build(                /*Sample1.class.getClassLoader().getResourceAsStream("/text.xml")*/                "D:/Workspaces/Eclipse/ImitateSpring/bin/yuki/spring/imitate/xml/test.xml");        Element root = document.getRootElement();        List<Element> elements = root.getChildren();        for(Element element : elements){            String name = element.getAttributeValue("name");            String capacity = element.getChildText("capacity");            String directories = element.getChildText("directories");            String files = element.getChildText("files");            System.out.println("磁盘信息:");            System.out.println("分区盘符:" + name);            System.out.println("分区容量:" + capacity);            System.out.println("目录数:" + directories);            System.out.println("文件数:" + files);            System.out.println("------------------------------");        }            }}

 

运行结果如下:

磁盘信息:分区盘符:C分区容量:8G目录数:200文件数:1580------------------------------磁盘信息:分区盘符:D分区容量:10G目录数:500文件数:3000------------------------------

 

可以把bean作为另一个bean的属性注入

/ImitateSpring/src/beans.xml

<?xml version="1.0" encoding="UTF-8"?><beans>    <bean id="u" class="yuki.spring.imitate.dao.impl.UserDAOImpl"></bean>    <bean id="userService" class="yuki.spring.imitate.service.UserService">        <property name="userDAO" bean="u"></property>    </bean></beans>

 

/ImitateSpring/src/yuki/spring/imitate/spring/BeanFactory.java

package yuki.spring.imitate.spring;public interface BeanFactory {    Object getBean(String name);}

 

/ImitateSpring/src/yuki/spring/imitate/spring/ClassPathXmlApplicationContext.java

package yuki.spring.imitate.spring;import java.lang.reflect.Method;import java.util.HashMap;import java.util.List;import java.util.Map;import org.jdom2.Document;import org.jdom2.Element;import org.jdom2.input.SAXBuilder;public class ClassPathXmlApplicationContext implements BeanFactory {    private Map<String, Object> beans = new HashMap<String, Object>();        public ClassPathXmlApplicationContext() throws Exception {        SAXBuilder saxBuilder = new SAXBuilder();        Document document = saxBuilder.build(                "D:/Workspaces/Eclipse/ImitateSpring/bin/beans.xml");        Element root = document.getRootElement();        List<Element> elements = root.getChildren();        for(Element element : elements){            String id = element.getAttributeValue("id");            String clazz = element.getAttributeValue("class");            System.out.println(id + " : " + clazz);            Object o = Class.forName(clazz).newInstance();            beans.put(id, o);                        for(Element propertyElement : element.getChildren("property")){                String name = propertyElement.getAttributeValue("name");                String bean = propertyElement.getAttributeValue("bean");                Object beanObject = beans.get(bean);                                String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);                System.out.println("method name = " + methodName);                                Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);                m.invoke(o, beanObject);            }        }    }    @Override    public Object getBean(String name){        return beans.get(name);    }}

 

通过JUnit,可以新建测试类

/ImitateSpring/test/yuki/spring/imitate/service/UserServiceTest.java

package yuki.spring.imitate.service;import org.junit.Test;import yuki.spring.imitate.pojo.User;import yuki.spring.imitate.spring.BeanFactory;import yuki.spring.imitate.spring.ClassPathXmlApplicationContext;public class UserServiceTest {    @Test    public void testAdd() throws Exception {        BeanFactory factory = new ClassPathXmlApplicationContext();        UserService service = (UserService) factory.getBean("userService");        /*UserDAO userDAO = (UserDAO) factory.getBean("u");        service.setUserDAO(userDAO);*/        User u = new User();        service.add(u);    }}

 

运行结果如下:

u : yuki.spring.imitate.dao.impl.UserDAOImpluserService : yuki.spring.imitate.service.UserServicemethod name = setUserDAOuser saved...

 

术语解释:

控制反转(IOC)、依赖注入(DI)
本来应该自己控制的,交给容器控制,可以实现随意装配

 

本文参考了[尚学堂马士兵_Spring_模拟Spring]的公开课程

更多好文请关注:http://www.cnblogs.com/kodoyang/

 

Spring依赖注入 --- 模拟实现