模拟spring

本文详细阐述了如何将用户信息进行持久化,并通过Spring框架实现了从测试到服务层的逐步构建,最终通过配置文件灵活管理持久化层。讨论了在不同场景下如何通过配置文件动态替换持久化实现,以及将用户信息写入文件的解决方案。
摘要由CSDN通过智能技术生成

需求:

把用户信息进行持久化。

分析:

1、提取需求中的实体类:用户信息,定义类:User,包含name和age两个field

2、分层。根据需求可分为用户服务和持久化层;

一、传统方法实现:

1、写持久层测试用例

package com.gll.spring.ioc.dao;

import com.gll.spring.ioc.model.User;
import org.junit.Test;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

/**
 * Created by Administrator on 2015/4/4.
 */
public class UserDaoTest {
    @Test
    public void should_return_true_when_save_user() throws Exception {

        UserDao userDao = new UserDao();

        User user = new User();

        assertThat(userDao.save(user),is(true));
    }
}

 3、消除测试用例中的错误,创建实体类User和持久化类DaoUser,并运行测试用例并通过:

package com.gll.spring.ioc.model;

/**
 * Created by Administrator on 2015/4/4.
 */
public class User {

    private String name;

    private String age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}

 

package com.gll.spring.ioc.dao;

import com.gll.spring.ioc.model.User;

/**
 * Created by Administrator on 2015/4/4.
 */
public class UserDao {
    public boolean save(User user) {
        return true;
    }
}

4、先写服务层测用例,消除用例中的错误并使用例通过,代码如下:

  

package com.gll.spring.ioc.service;

import com.gll.spring.ioc.dao.UserDao;
import com.gll.spring.ioc.model.User;
import org.junit.Test;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

/**
 * Created by Administrator on 2015/4/4.
 */
public class UserServiceTest {

    @Test
    public void should_return_true_when_add_user() throws Exception {

        UserService userService = new UserService();

        userService.setUserDao(new UserDao());
        
        User user = new User();
        assertThat(userService.add(user),is(true));
    }
}

  

package com.gll.spring.ioc.service;

import com.gll.spring.ioc.dao.UserDao;
import com.gll.spring.ioc.model.User;

/**
 * Created by Administrator on 2015/4/4.
 */
public class UserService {
    private UserDao userDao;

    public boolean add(User user) {
        return userDao.save(user);
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}

 5、完成需求,问题:

      需求变更:用户信息存储到多个数据库或文件中时,则需要修改代码,由开发者控制实现。

二、模拟spring实现

1、考虑在配置文件中配置Dao的具体实现类,增加一个接口BeanFactory:

package com.gll.spring.simulation;

/**
 * Created by Administrator on 2015/4/4.
 */
public interface BeanFactory {

    Object getBean(String var);
}

 

2、定义配置文件simulation.xml,格式如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <bean id="userDao" class="com.gll.spring.ioc.dao.UserDao"></bean>
    <bean id="userService" class="com.gll.spring.ioc.service.UserService">
        <property name="userDao" ref="userDao"></property>
    </bean>
</beans>

 3、写一个解析simulation.xml文件的测试用例

package com.gll.spring.simulation;

import com.gll.spring.ioc.dao.UserDao;
import org.junit.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;

/**
 * Created by Administrator on 2015/4/4.
 */
public class ClassPathXmlApplicationContextTest {
    @Test
    public void should_return_class_UserDao_when_get_bean_by_userDao() throws Exception {

        BeanFactory ctx = new ClassPathXmlApplicationContext();

        assertThat(ctx.getBean("userDao").getClass().getName(),is(UserDao.class.getName()));
    }
}

 4、消除测试用例中的错误,运行测试用例,此时用例不通过,实现解析simulation.xml文件直到用例通过:

package com.gll.spring.simulation;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2015/4/4.
 */
public class ClassPathXmlApplicationContext implements BeanFactory {

    private final Map<String, Object> beans = new HashMap<String, Object>();

    public ClassPathXmlApplicationContext() throws Exception {

        SAXBuilder builder = new SAXBuilder();
        Document build = builder.build(this.getClass().getClassLoader().getResourceAsStream("simulation.xml"));
        Element rootElement = build.getRootElement();

        List<Element> elements = rootElement.getChildren("bean");

        for (int i = 0; i < elements.size(); i++) {

            Element element = elements.get(i);
            String id = element.getAttributeValue("id");
            String clazz = element.getAttributeValue("class");

            Object instance = Class.forName(clazz).newInstance();

            beans.put(id, instance);
        }
    }

    @Override
    public Object getBean(String var) {
        return beans.get(var);
    }
}

 5、写第二个测试用例,把UserDao注入到UserService中:

    @Test
    public void userDao_not_null_when_get_userDao_in_userService() throws Exception {

        UserService userService = (UserService) ctx.getBean("userService");

        assertThat(userService.getUserDao().getClass().getName(), is(UserDaoImpl.class.getName()));
    }

 该过程需要把UserDao提取成一个接口,实现setter注入,运行所有测试用例,直到所有测试通过:

package com.gll.spring.simulation;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2015/4/4.
 */
public class ClassPathXmlApplicationContext implements BeanFactory {

    private final Map<String, Object> beans = new HashMap<String, Object>();

    @Override
    public Object getBean(String id) {
        return beans.get(id);
    }

    public ClassPathXmlApplicationContext() throws Exception {

        SAXBuilder builder = new SAXBuilder();
        Document build = builder.build(this.getClass().getClassLoader().getResourceAsStream("simulation.xml"));
        Element rootElement = build.getRootElement();

        List<Element> elements = rootElement.getChildren("bean");

        buildObjectDI(elements);
    }

    private void buildObjectDI(List<Element> elements) throws Exception {
        for (int i = 0; i < elements.size(); i++) {

            Element element = elements.get(i);
            String id = element.getAttributeValue("id");
            String clazz = element.getAttributeValue("class");

            Object instance = Class.forName(clazz).newInstance();

            beans.put(id, instance);

            List<Element> properties = element.getChildren("property");

            BuildSetterDI(instance, properties);
        }
    }

    private void BuildSetterDI(Object instance, List<Element> properties) throws Exception {
        for (int j = 0; j < properties.size(); j++) {

            Element property = properties.get(j);
            String name = property.getAttributeValue("name");
            String ref = property.getAttributeValue("ref");
            Object field = beans.get(ref);

            String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);

            Method method = instance.getClass().getMethod(methodName, field.getClass().getInterfaces()[0]);

            method.invoke(instance, field);
        }
    }
}

 6、如果用户信息写到文件中,则增加写文件类FileUserDaoImpl.java,修改配置simulation.xml则可。

 

说明:例子采用先写测试后写实现的方式开发但用例跨度有点大,整个过程还伴随了重构。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值