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. CentOS禁用root本地或远程ssh登录

    有些特殊的情况我们需要禁止root在本地或远程使用ssh登录,以增加安全性. 禁止root本地登录 修改/etc/pam.d/login文件增加下面一行auth required pam_succee ...

  2. C# 中通过API实现的打印类

    using System;using System.Collections;using System.Text;using System.Runtime.InteropServices; using ...

  3. Oracle —— 表结构相关的SQL

    1.表基本信息(Table) select * from user_tables t, user_tab_comments c where c.table_name = t.table_name an ...

  4. PHP 日期格式:yyyy-MM-dd'T'HH:mm:ss.SSSZ 的写法

    今日在写一个接口是,其中有一个时间参数的格式是 yyyy-MM-dd'T'HH:mm:ss.SSSZ 查了一下最后的SSSZ SSS毫秒 Z代表时区 'T' 就是固定字符T,也有的指的是任意字符,本接 ...

  5. [Topcoder]ZigZag(dp)

    题目链接:https://community.topcoder.com/stat?c=problem_statement&pm=1259&rd=4493 题意:给一串数字,求出最长的波 ...

  6. 好!maximum-product-of-word-lengths

    以后看到个数比较少,性能比较高,就要第一时间想到位操作! 这道题目mock没有通过.超时了...... 原来题目解法的思路非常非常好! 开始我关注于降低n*n的复杂度,但是这道题目复杂度高在每个字符串 ...

  7. poj 2096 Collecting Bugs (概率dp 天数期望)

    题目链接 题意: 一个人受雇于某公司要找出某个软件的bugs和subcomponents,这个软件一共有n个bugs和s个subcomponents,每次他都能同时随机发现1个bug和1个subcom ...

  8. android异步任务详解 AsynTask

    android提供了一套专门用于异步处理的类.即:AynsTask类.使用这个类可以为耗时程序开辟一个新线程进行处理,处理完时返回. 其实,AsynTask类就是对Thread类的一个封装,并且加入了 ...

  9. HNOI2008题目总结

    呜呼..NOI前一个月正式开始切BZOJ了……以后的题解可能不会像之前的零散风格了,一套题我会集中起来发,遇到一些需要展开总结的东西我会另开文章详细介绍. 用了一天的时间把HNOI2008这套题切了… ...

  10. Scrum Agile

    Scrum Agile 迭代式增量软件开发,敏捷开发,源于丰田汽车的制造流程. HMC测试流程: 1.hmc改配置 2.上ui验证 3.还原hmm(有的需要,有的不需要) 4.addReferal,在 ...