也是重新整理了之前的那篇

    模仿Mybatis用map

per.xml实现Dao层接口的功能

话不多说直接上代码

首先是结构

依赖pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>yebatis</groupId>
    <artifactId>com.yck.yebatis</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.42</version>
        </dependency>
    </dependencies>

</project>

一些基本类

用来封装一个dao信息的Mapper类

package com.yck.yebaitis;

import java.util.List;

public class Mapper {

    private String mapperClass;
    private List<Function> functions;

    public String getMapperClass() {
        return mapperClass;
    }

    public void setMapperClass(String mapperClass) {
        this.mapperClass = mapperClass;
    }

    public List<Function> getFunctions() {
        return functions;
    }

    public void setFunctions(List<Function> functions) {
        this.functions = functions;
    }
}

封装一条方法信息的Function类

package com.yck.yebaitis;

public class Function {
    private String name;
    private String type;
    private Class<?> resultClass;
    private String sql;

    public String getName() {
        return name;
    }

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

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Class<?> getResultClass() {
        return resultClass;
    }

    public void setResultClass(Class<?> resultClass) {
        this.resultClass = resultClass;
    }

    public String getSql() {
        return sql;
    }

    public void setSql(String sql) {
        this.sql = sql;
    }
}

常量

package com.yck.yebaitis;

public class FunctionConstants {
    public static final String ADD = "add";
    public static final String DELETE = "delete";
    public static final String UPDATE = "update";
    public static final String SELECT = "select";

}

实现功能的DaoFactory

package com.yck.yebaitis;

import com.yck.jdbc.DataUtil;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.yck.util.StringUtil;
import com.yck.exception.NoConfigFileException;

import java.io.File;
import java.io.FileFilter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.*;

public class DaoFactory {

    private static final String configPath = "src/dao/mapper";
    private static DaoFactory instance;

    private DaoFactory() {
    }

    public static DaoFactory getInstance() {
        if (instance == null) {
            synchronized (DaoFactory.class) {
                if (instance == null)
                    instance = new DaoFactory();
            }
        }
        return instance;
    }

    public Map<String, Object> getDaoMap() {
        Map<String, Object> map = null;
        try {
            File[] files = getAllFiles();
            map = new HashMap<>(files.length);
            for (File file : files) {
                Mapper mapper = readerMapper(file);
                Object obj = implDao(mapper);
                map.put(mapper.getMapperClass(), obj);

            }
        } catch (NoConfigFileException | ClassNotFoundException | DocumentException e) {
            e.printStackTrace();
        }
        return map;
    }

    private Object implDao(Mapper mapper) throws ClassNotFoundException {
        ClassLoader classLoader = DaoFactory.class.getClassLoader();
        final Mapper temp = mapper;
        //加载一个接口类
        Class<?> interfaze;
        interfaze = classLoader.loadClass(mapper.getMapperClass());

        /*
        代理实现方法
        之前我是理解错了,我以为是在执行下面这个方法时,就已经实现了类似我们自己写一个DaoImpl,其实它就只是返回了一个代理类实例
         */
        return Proxy.newProxyInstance(classLoader, new Class[]{interfaze}, new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) {
                List<Function> functions = temp.getFunctions();
                for (Function func : functions) {
                    if (func.getName().equals(method.getName())) {
                        if (func.getType().equals(FunctionConstants.SELECT)) {
                            if (method.getReturnType().equals(List.class)) {
                                return DataUtil.queryForList(func.getSql(), func.getResultClass(), args);
                            } else {
                                return DataUtil.queryForObject(func.getSql(), func.getResultClass(), args);
                            }
                        } else {
                            return DataUtil.excuteUpdate(func.getSql(), args);
                        }
                    }
                }
                return null;
            }
        });
    }

    private File[] getAllFiles() throws NoConfigFileException {

        FileFilter fileFilter = new FileFilter() {
            public boolean accept(File pathname) {
                String fileName = pathname.getName().toLowerCase();
                return fileName.endsWith(".xml");
            }
        };
        File configPath = new File("src/mapper");
        File[] files = configPath.listFiles(fileFilter);
        if (files == null || files.length == 0) {
            throw new NoConfigFileException("file not find");
        }
        return files;
    }

    private Mapper readerMapper(File file) throws DocumentException, ClassNotFoundException {
        SAXReader reader = new SAXReader();
        Mapper mapper = new Mapper();

        Document doc = reader.read(file);
        Element root = doc.getRootElement(); //读取根节点 即dao节点
        mapper.setMapperClass(root.attributeValue("class").trim()); //把dao节点的class值存为接口名
        List<Function> list = new ArrayList<>(); //用来存储方法的List
        for (Iterator<?> rootIter = root.elementIterator(); rootIter.hasNext(); ) //遍历根节点下所有子节点
        {
            Function fun = new Function();    //用来存储一条方法的信息
            Element e = (Element) rootIter.next();
            String type = e.getName().trim();
            switch (type) {
                case FunctionConstants.ADD:
                    fun.setType(FunctionConstants.ADD);
                    break;
                case FunctionConstants.DELETE:
                    fun.setType(FunctionConstants.DELETE);
                    break;
                case FunctionConstants.UPDATE:
                    fun.setType(FunctionConstants.UPDATE);
                    break;
                case FunctionConstants.SELECT:
                    fun.setType(FunctionConstants.SELECT);
                    break;
                default:
                    continue;
            }
            fun.setName(e.attributeValue("id").trim());
            fun.setSql(e.getText().trim());
            String resultType = e.attributeValue("resultType");
            if (!StringUtil.isBlank(resultType)) {
                fun.setResultClass(Class.forName(resultType));
            }
            list.add(fun);
        }
        mapper.setFunctions(list);
        return mapper;
    }
}

测试用类

 

实现IUserDao的xml文件就是最底下的userdao.xml

<?xml version="1.0" encoding="UTF-8"?>
<dao id="userdao" class="dao.IUserDao">

    <select id="selectById" resultType ="po.User">
        select * from t_user where id = ?
    </select>

    <update id="updateName">
        update t_user set name = ? where id = ?
    </update>

    <delete id="deleteById">
        delete from t_user where id=?
    </delete>

    <insert id="add">
        insert into t_user(name,age,score,create_time,update_time)
        values(?,?,?,now(),now());
    </insert>

    <select id="getAll" resultType = "po.User">
        select * from t_user;
    </select>

</dao>

测试代码

import com.yck.yebaitis.DaoFactory;
import dao.IUserDao;
import po.User;

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

public class Test {

    public static void main(String[] args) {

        Map<String,Object> daoMap = DaoFactory.getInstance().getDaoMap();
        IUserDao dao = (IUserDao) daoMap.get("dao.IUserDao");
        List<User>  users = dao.getAll();
        System.out.println("查询多条记录:"+users);
        System.out.println("*******************************************");

        User user = dao.selectById(2);
        System.out.println("查询一条记录:"+user);
        System.out.println("*******************************************");

        int i = dao.updateName("二傻",2);
        System.out.println("更新一条记录:"+i);
        System.out.println("*******************************************");

        List<User> userList = dao.getAll();
        System.out.println("更新一条记录后查询所有记录:"+user);
        System.out.println("*******************************************");

    }
}

测试结果

大王让我写代码 23:15:19

瞎j8封装第二版之用xml文件来代理dao接口的更多相关文章

  1. 瞎j8封装第二版之数据层的封装

    看了以前写的代码,对就是下面这个 手把手封装数据层之DataUtil数据库操作的封装 觉得以前写的代码好烂啊!!!,重新理了一下思路,写得更规范和简练,应该效率也会高很多,用了一下下午写的连接池(半废 ...

  2. 瞎j8封装第二版之数据库连接池

    写得很蛋疼,本来想支持多线程的,奈何对多线程和连接池理解着实太菜: 所以,起码是能拿到连接了... 但是还是不太懂这个连接池 我也是半抄别人的,以后再搞一搞这个吧. 先是配置文件 理想是很丰满的,奈何 ...

  3. 一只菜鸟的瞎J8封装系列的目录

    因为这是一个系列...也就是我们所说的依赖关系.后面很多方法都是基于我前面封装的工具来进行的,所以我列一个目录供大家参考... 一只菜鸟的瞎J8封装系列  一.手把手封装数据层之DButil数据库连接 ...

  4. 计算器-- 利用re模块 利用函数封装 第二版

    import re remove_parentheses = re.compile('\([^()]+\)') def Remove_Parentheses(obj, s): # 找到内层的括号并且返 ...

  5. Idea mybatis maper接口与mapper.xml文件关联 会根据接口中的方法点在mxl中生成相应sql方法

  6. mapper.xml是怎样实现Dao层接口

    上午写了一个简单的 从xml读取信息实例化一个Bean对象.下午就开始想mybatis是怎么通过xml文件来实现dao层接口的,一开始想直接用Class.forName(String name)然后调 ...

  7. java Domj4读取xml文件

    先概括,再以代码形式给出. 获取节点: Iterator  Element.nodeIterator();  //获取当前标签节点下的所有子节点 获取 标签: Element Document.get ...

  8. mybatis 基础(二) xml文件中的其他知识点

    mybatis xml文件中一些标签的使用 此标签主要用作 配置 "别名" 如果实体类与数据库中字段名在不区分大小写的情况下相同的话, 那就不需要配置resultMap,因为mys ...

  9. MyBatis(七):使用注解替代xml文件

    本文是按照狂神说的教学视频学习的笔记,强力推荐,教学深入浅出一遍就懂!b站搜索狂神说或点击下面链接 https://space.bilibili.com/95256449?spm_id_from=33 ...

随机推荐

  1. IT连创业系列:App产品上线后,运营怎么搞?(中)

    等运营篇写完,计划是想写一个IOS系列,把IT连App里用到和遇到的坑都完整的和大伙分享. 不过写IOS系列前,还是要认真把这个运营篇写完,接下来好好码字!!! 上篇说到,我们计划去一次富士康门口,拉 ...

  2. easyUI整合富文本编辑器KindEditor详细教程(附源码)

    原因 在今年4月份的时候写过一篇关于easyui整合UEditor的文章Spring+SpringMVC+MyBatis+easyUI整合优化篇(六)easyUI与富文本编辑器UEditor整合,从那 ...

  3. memcached复制-repcached

    1.前言 由于memcached把数据都放到内存里,因此性能是极高的,正因为如此,不可避免会造成数据丢失,repcached就派上用场了,它可以实现memcached的主从复制 2.安装repcach ...

  4. leetcode#42 Trapping rain water的五种解法详解

    leetcode#42 Trapping rain water 这道题十分有意思,可以用很多方法做出来,每种方法的思想都值得让人细细体会. 42. Trapping Rain WaterGiven n ...

  5. ##7.Dashboard web管理界面-- openstack pike

    ##7.Dashboard web管理界面 openstack pike 安装 目录汇总 http://www.cnblogs.com/elvi/p/7613861.html ##.Dashboard ...

  6. 百度OCR文字识别-身份证识别

    简介 一.介绍 身份证识别 API 接口文档地址:http://ai.baidu.com/docs#/OCR-API/top 接口描述 用户向服务请求识别身份证,身份证识别包括正面和背面. 请求说明 ...

  7. CCF-201509-3-生成模板系统

    问题描述 试题编号: 201509-3 试题名称: 模板生成系统 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 成成最近在搭建一个网站,其中一些页面的部分内容来自数据库中不同 ...

  8. linux运维、架构之路-Zabbix监控应用及分布式

    一.Zabbix监控集群应用 1.监控端口 net.tcp.listen[port] 检查 TCP 端口 是否处于侦听状态.返回 0 - 未侦听:1 - 正在侦听 net.tcp.port[<i ...

  9. UWP 共享文件——接收者

    UWP上共享,分为接收者(别人共享数据给你,你接收了,然后在做你的处理)和发送者(你给别人发送数据,就像你的App支持图片共享到微信好友或者朋友圈那样,虽然UWP上的微信并不支持这样子) 很简单(参考 ...

  10. Python的控制语句

    1.  控制语句 控制语句是用来改变程序执行的顺序.程序利用控制语句有条件地执行语句,循环地执行语句或者跳转到程序中的其他部分执行语句. Python支持三种不同的控制语句:if,for和while, ...