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.UserDAOImpl
userService : yuki.spring.imitate.service.UserService
method name = setUserDAO
user saved...

术语解释:

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

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

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

Spring依赖注入 --- 模拟实现的更多相关文章

  1. (转)编码剖析Spring依赖注入的原理

    http://blog.csdn.net/yerenyuan_pku/article/details/52834561 Spring的依赖注入 前面我们就已经讲过所谓依赖注入就是指:在运行期,由外部容 ...

  2. Spring依赖注入(IOC)那些事

    小菜使用Spring有几个月了,但是对于它的内部原理,却是一头雾水,这次借着工作中遇到的一个小问题,来总结一下Spring. Spring依赖注入的思想,就是把对象交由Spring容器管理,使用者只需 ...

  3. Spring依赖注入三种方式详解

    在讲解Spring依赖注入之前的准备工作: 下载包含Spring的工具jar包的压缩包 解压缩下载下来的Spring压缩包文件 解压缩之后我们会看到libs文件夹下有许多jar包,而我们只需要其中的c ...

  4. Spring依赖注入:注解注入总结

    更多11   spring   依赖注入   注解   java 注解注入顾名思义就是通过注解来实现注入,Spring和注入相关的常见注解有Autowired.Resource.Qualifier.S ...

  5. Spring 依赖注入,在Main方法中取得Spring控制的实例

    Spring依赖注入机制,在Main方法中通过读取配置文件,获取Spring注入的bean实例.这种应用在实训的时候,老师曾经说过这种方法,而且学Spring入门的时候都会先学会使用如何在普通的jav ...

  6. Spring依赖注入 --- 简单使用说明

    Spring依赖注入 --- 简单使用说明 本文将对spring依赖注入的使用做简单的说明,enjoy your time! 1.使用Spring提供的依赖注入 对spring依赖注入的实现方法感兴趣 ...

  7. Java Web系列:Spring依赖注入基础

    一.Spring简介 1.Spring简化Java开发 Spring Framework是一个应用框架,框架一般是半成品,我们在框架的基础上可以不用每个项目自己实现架构.基础设施和常用功能性组件,而是 ...

  8. Spring依赖注入的三种方式

    看过几篇关于Spring依赖注入的文章,自己简单总结了一下,大概有三种方式: 1.自动装配 通过配置applicationContext.xml中的标签的default-autowire属性,或者标签 ...

  9. spring依赖注入源码分析和mongodb自带连接本地mongodb服务逻辑分析

    spring依赖注入本质是一个Map结构,key是beanId,value是bean对应的Object. autowired是怎么将定义的接口与对应的bean类建立联系? <bean name= ...

随机推荐

  1. jboss内存管理

    jboss内存查看 1. 用浏览器打开网址:http://IP:port/jmx-console/ 2. 找到 jboss.system 一节,或者在 filter 文本框中输入 jboss.syst ...

  2. Write operations are not allowed in read-only mode

    使用Spring提供的Open Session In View而引起Write operations are not allowed in read-only mode (FlushMode.NEVE ...

  3. linux怎么运行.SH文件

    执行sh xx.sh命令就可以执行.sh文件了.如果直接执行xx.sh文件,就报权限错误 解决办法:执行chmod u+x xx.sh 来添加执行权限

  4. PHP 练习租房

    练习:租房子 <body> <form action="test.php" method="post"> <div>区域: ...

  5. 【USACO】Transformations

    A square pattern of size N x N (1 <= N <= 10) black and white square tiles is transformed into ...

  6. 超大整数运算算法——为RSA加密算法提供运算工具

    /* program: Large integer operations * Made by:  Daiyyr * date:  2013/07/09 * This software is licen ...

  7. U3D NGUI改变GameObject Activity闪烁的问题

    不是关闭再激活GameObject会闪烁,而是再激活时,NGUI渲染步骤不一致导致的闪烁. 并且文字激活后渲染要慢一帧,如果延迟一帧处理,又会导致精灵图片快一帧,图片重叠.这个测试结果不一定准确,先记 ...

  8. 用Eclipse+ADT创建可运行项目,创建lib项目,引用一个lib项目

    Managing Projects from Eclipse with ADT In this document Creating an Android Project  创建可运行项目 Settin ...

  9. php-redis中文文档(转)

    phpredis是php的一个扩展,效率是相当高有链表排序功能,对创建内存级的模块业务关系 很有用;以下是redis官方提供的命令使用技巧: 下载地址如下: https://github.com/ow ...

  10. Android 用户界面---拖放(Drag and Drop)(三)

      设计拖放操作 本节主要内容如下: 1.  如何开始拖拽: 2.  在拖拽期间如何响应事件: 3.  如何响应落下事件: 4.  如何结束拖放操作. 开始拖拽 用户使用一个拖拽手势开始拖拽,通常是在 ...