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. Linux系统中的load average

    1. load average 定义 linux系统中的Load对当前CPU工作量的度量.简单的说是进程队列的长度. Load Average 就是一段时间 (1 分钟.5分钟.15分钟) 内平均 L ...

  2. 动态库加载出错,cannot restore segment prot after reloc: Permission denied

    转自:taolinke的博客 项目中碰到的问题,编译好的so文件,放到其他机器上去加载,报了错误,cannot restore segment prot after reloc: Permission ...

  3. AIX 内存使用情况

    cat > WHAT_EVER_YOU_WANT.sh#!/usr/bin/ksh#memory calculatorum=`svmon -G | head -2|tail -1| awk {' ...

  4. 《OD大数据实战》Flume环境搭建

    一.CentOS 6.4安装Nginx http://shiyanjun.cn/archives/72.html 二.安装Flume 1. 下载flume-ng-1.5.0-cdh5.3.6.tar. ...

  5. Android应用加入微信分享

    一.申请你的AppID http://open.weixin.qq.com/ 友情提示:推荐使用eclipse打包软件最后一步的MD5值去申请AppID 二.官网下载libammsdk.jar包 ht ...

  6. [Android] Android开发优化之——使用软引用和弱引用

      Java从JDK1.2版本开始,就把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期.这四种级别由高到低依次为:强引用.软引用.弱引用和虚引用. 这里重点介绍一下软引用和弱引用. ...

  7. 浏览器兼容的css hack

    <style> div{ background:green; /* for firefox */ *background:red; /* for IE6 */ } </style&g ...

  8. xxx cannot be resolved to a type 错误解决方法

    (1)jdk不匹配(或不存在)     项目指定的jdk为“jdk1.6.0_18”,而当前eclipse使用的是“jdk1.6.0_22”.需要在BuildPath | Libraries,中做简单 ...

  9. UVa 644 Immediate Decodability

    吐槽下我的渣渣英语啊,即使叫谷歌翻译也没有看懂,最后还是自己读了好几遍题才读懂. 题目大意:题意很简单,就是给一些互不相同的由'0','1'组成的字符串,看看有没有一个字符串是否会成为另一个的开头的子 ...

  10. kafka_2.9.2-0.8.1.1分布式集群搭建代码开发实例

    准备3台虚拟机, 系统是RHEL64服务版. 1) 每台机器配置如下:$ cat /etc/hosts    # zookeeper hostnames:       192.168.8.182    ...