动态代理在mybatis接口式编程中的应用
来源:互联网 发布:提高智商知乎 编辑:程序博客网 时间:2024/06/12 01:42
上一篇文章着重介绍了jdk动态代理的实现和简要介绍了其实现原理,这一篇文章来介绍一下动态代理在mybatis接口式编程中的应用,希望自己以后也能有机会去写写架构。
mybatis通过一个配置文件和一个接口就可以完成sql语句的具体执行,其过程如下:
1.编写一个提供执行SQL的接口
import java.util.List;import java.util.Map;import com.imooc.bean.Member;/** * 与member配置文件相对应的接口 * @author user * */public interface IMember {/** * 根据查询条件查询消息列表 */public List<Member> queryMemberList(Map map);/** * 根据查询条件查询消息列表的条数 */public int count(Member member);/** * 根据查询条件分页查询消息列表 */public List<Member> queryMemberListByPage(Map<String,Object> parameter);}
2.编写供上面接口引用的SQL配置文件
<?xml version="1.0" encoding="UTF-8"?><!-- Copyright 2009-2012 the original author or authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.--><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.dao.IMember"> <resultMap type="com.bean.Member" id="MemberResult"> <id column="MEMBER_ID" jdbcType="BIGINT" property="id"/> <result column="FULL_NAME" jdbcType="NVARCHAR" property="fullName"/> <result column="DATE_OF_BIRTH" jdbcType="DATE" property="dateOfBirth"/> </resultMap> <select id="queryMemberList" parameterType = "java.util.Map" resultMap="MemberResult"> SELECT TOP ${page.dbNumber} MEMBER_ID,FULL_NAME,DATE_OF_BIRTH FROM (SELECT ROW_NUMBER() OVER(ORDER BY MEMBER_ID) AS ROWNUMBER,MEMBER_ID,FULL_NAME,DATE_OF_BIRTH FROM MEMBER <where> <if test="member.fullName != null and !"".equals(member.fullName.trim())">AND FULL_NAME = #{member.fullName}</if> </where> ) TABLE_MEMBER WHERE ROWNUMBER > ${page.dbIndex} </select> <select id="count" parameterType="com.bean.Member" resultType="int"> SELECT COUNT(*) FROM MEMBER <where> <if test="fullName != null and !"".equals(fullName.trim())">AND FULL_NAME LIKE #{fullName}</if> </where> </select> <select id="queryMemberListByPage" parameterType="java.util.Map" resultMap="MemberResult"> SELECT MEMBER_ID,FULL_NAME,DATE_OF_BIRTH FROM MEMBER <where> <if test="member.fullName != null and !"".equals(member.fullName.trim())">AND FULL_NAME LIKE #{member.fullName}</if> </where> ORDER BY MEMBER_ID </select> <delete id="deleteOne" parameterType="int"> DELETE FROM MEMBER WHERE id = #{_parameter} </delete> <delete id="deleteBatch" parameterType="java.util.List"> DELETE FROM MEMBER WHERE 1 = 1 AND MEMBER_ID IN (<foreach collection="list" item="item" separator=","> #{item} </foreach> ) </delete></mapper>
3.DAO方法调用接口方法执行SQL
/** * 根据查询条件查询消息列表 */public List<Member> queryMemberList(Map<String,Object> parameter) {DBAccess dbAccess = new DBAccess();List<Member> memberList = new ArrayList<Member>();SqlSession sqlSession = null;try {sqlSession = dbAccess.getSqlSession();// 通过sqlSession执行SQL语句IMember imember = sqlSession.getMapper(IMember.class);memberList = imember.queryMemberList(parameter);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {if(sqlSession != null) {sqlSession.close();}}return memberList;}
DAO调用方法在执行sqlSession.getMapper(IMember.class);这句时,mybatis实际帮我们返回了一个IMember接口的具体实例,这里被代理方就是sqlSession,而代理类的类型就是IMember(由参数指定)
1.mybatis在解析配置文件时,根据namespace就可以知道哪些接口可以生成代理对象,并且为这些接口生成一个map,map的key就是具体的class(本例中为IMember.class),value是一个MapperProxyFactory<T>的一个实例,这个实例有一个Class<T>类型的属性(本例中为IMember.class)并且实现了InvocationHandler接口
2.通过跟踪mybatis的源码(下面按顺序列出生成代理实例过程中流转到的语句),发现最终生成代理类实例的语句为下面的第(7)句
(1).sqlSession.getMapper(IMember.class);
(2).configuration.<T>getMapper(type, this);//这里this就是sqlSession
(3).mapperRegistry.getMapper(type, sqlSession);
(4).final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
(5).mapperProxyFactory.newInstance(sqlSession);
(6). final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);//MapperProxy<T>实现了InvocationHandler接口
(7).(T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
这里需要注意的是,sqlSession作为被代理对象并没有实现IMember接口,也没有定义任何与IMember相同的方法,但是当我们执行代理类对象的任何方法时,sqlSession都可以被调用。这是因为MapperProxy<T>(可以植入代理行为的InvocationHandler实现)类的invoke方法中并没有使用反射来直接触发被代理方(IMember)方法的执行,而是通过解析传入的被代理方法对象(Method参数)重新分析sqlSession对象完成SQL的执行,而sqlSession作为MapperProxy<T>类的属性,在其执行invoke方法时被直接引用。这就是上一篇文章中结尾处提到了,当被代理对象(目标对象)没有实现jdk要求的接口,但我们仍希望jdk可以帮我们返回一个接口的代理实现对象时,就需要在InvocationHandler实现类的invoke方法中直接调用被代理对象需要执行的方法而不能通过反射来触发,此处被代理对象(目标对象)和InvocationHandler的实现类是耦合的。
- 动态代理在mybatis接口式编程中的应用
- 理解动态代理及动态代理在RPC中的应用
- 动态代理在spring中的应用
- 动态代理在Spring AOP中的应用
- 动态代理及其在Spring中的应用
- 动态代理技术在JavaWeb中的应用
- 反射机制在代理中的应用(二) 动态代理
- MyBatis的Mapper接口动态代理
- 动态代理在JDBC的DataSource中的应用
- JAVA的Proxy动态代理在自动化测试中的应用
- 【反射+注解+动态代理在事务中的应用service层】
- 反射机制在代理中的应用(三) 动态代理中的反射机制
- 代理与异常定制在PHP5 OOP编程中的应用
- Mybatis中的反射和动态代理
- Mybatis接口式编程
- mybatis接口式编程
- 粗略实现jdk中的接口动态代理
- 学习动态代理stepbystep(5)[应用jdk中的动态代理]
- 重构二叉树
- objective-c和java
- Flex datagrid单元格合并
- 知识点扫盲
- 视频会议图像因为qp值造成的灰屏的bug处理过程
- 动态代理在mybatis接口式编程中的应用
- php深入学习笔记二( 函数内置函数 )
- stm32需要的手册
- RPDB-让PDB(Python调试工具)支持远程调试功能
- 向注册表中注册文件类型
- Android中触摸事件传递过程
- add groups 配置
- 如何快速去除黑眼圈
- 在Ubuntu中安装kali tools