[SSM]MyBatis使用javassist生成类和接口代理机制

这篇具有很好参考价值的文章主要介绍了[SSM]MyBatis使用javassist生成类和接口代理机制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

六、使用javassist生成类

6.1Javassist的使用

6.2使用Javassist生成DaoImpl类

七、MyBatis中接口代理机制及使用

7.1在之前的web应用中使用接口代理机制

7.2使用接口代理机制完成之前的CRUD(部分代码)


六、使用javassist生成类

6.1Javassist的使用

引入javassist依赖

<dependency>
 <groupId>org.javassist</groupId>
 <artifactId>javassist</artifactId>
 <version>3.29.1-GA</version>
</dependency>

测试

 @Test
    public void testGenerateFirstClass() throws Exception {
        //获取类池,这个类池就是用来生成class的
        ClassPool pool = ClassPool.getDefault();
        //制造类(需要告诉javassist类名是什么)
        CtClass ctClass = pool.makeClass("com.hhb.dao.impl.AccountDaoImpl");
        //制造方法
        String methodCode = "public void insert(){System.out.println(123);}";
        CtMethod ctMethod = CtMethod.make(methodCode, ctClass);
        //将方法添加到类中
        ctClass.addMethod(ctMethod);
        //在内存中生成class
        ctClass.toClass();
​
        //类加载到JVM中,返回AccountDaoImpl类的字节码
        Class<?> clazz = Class.forName("com.hhb.dao.impl.AccountDaoImpl");
        //创建对象
        Object obj = clazz.newInstance();
        //获取AccountDaoImpl中的insert方法
        Method insertMethod = clazz.getDeclaredMethod("insert");
        //调用方法insert
        insertMethod.invoke(obj);
    }

6.2使用Javassist生成DaoImpl类

GenerateDaoProxy

package com.hhb.utils;
​
import org.apache.ibatis.javassist.ClassPool;
import org.apache.ibatis.javassist.CtClass;
import org.apache.ibatis.javassist.CtMethod;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.session.SqlSession;
​
import java.lang.reflect.Method;
import java.util.Arrays;
​
/**
 * 工具类:可以动态的生成DAO的实现类。(或者说可以动态生成DAO的代理类)
 * 注意注意注意注意注意!!!!!!:
 *      凡是使用GenerateDaoProxy的,SQLMapper.xml映射文件中namespace必须是dao接口的全名,id必须是dao接口中的方法名。
 */
public class GenerateDaoProxy { // GenerateDaoProxy是mybatis框架的开发者写的。
​
    /**
     * 生成dao接口实现类,并且将实现类的对象创建出来并返回。
     * @param daoInterface dao接口
     * @return dao接口实现类的实例化对象。
     */
    public static Object generate(SqlSession sqlSession, Class daoInterface){
        // 类池
        ClassPool pool = ClassPool.getDefault();
        // 制造类(com.powernode.bank.dao.AccountDao --> com.powernode.bank.dao.AccountDaoProxy)
        CtClass ctClass = pool.makeClass(daoInterface.getName() + "Proxy"); // 实际本质上就是在内存中动态生成一个代理类。
        // 制造接口
        CtClass ctInterface = pool.makeInterface(daoInterface.getName());
        // 实现接口
        ctClass.addInterface(ctInterface);
        // 实现接口中所有的方法
        Method[] methods = daoInterface.getDeclaredMethods();
        Arrays.stream(methods).forEach(method -> {
            // method是接口中的抽象方法
            // 将method这个抽象方法进行实现
            try {
                // Account selectByActno(String actno);
                // public Account selectByActno(String actno){ 代码; }
                StringBuilder methodCode = new StringBuilder();
                methodCode.append("public ");
                methodCode.append(method.getReturnType().getName());
                methodCode.append(" ");
                methodCode.append(method.getName());
                methodCode.append("(");
                // 需要方法的形式参数列表
                Class<?>[] parameterTypes = method.getParameterTypes();
                for (int i = 0; i < parameterTypes.length; i++) {
                    Class<?> parameterType = parameterTypes[i];
                    methodCode.append(parameterType.getName());
                    methodCode.append(" ");
                    methodCode.append("arg" + i);
                    if(i != parameterTypes.length - 1){
                        methodCode.append(",");
                    }
                }
                methodCode.append(")");
                methodCode.append("{");
                // 需要方法体当中的代码
                methodCode.append("org.apache.ibatis.session.SqlSession sqlSession = com.powernode.bank.utils.SqlSessionUtil.openSession();");
                // 需要知道是什么类型的sql语句
                // sql语句的id是框架使用者提供的,具有多变性。对于我框架的开发人员来说。我不知道。
                // 既然我框架开发者不知道sqlId,怎么办呢?mybatis框架的开发者于是就出台了一个规定:凡是使用GenerateDaoProxy机制的。
                // sqlId都不能随便写。namespace必须是dao接口的全限定名称。id必须是dao接口中方法名。
                String sqlId = daoInterface.getName() + "." + method.getName();
                SqlCommandType sqlCommandType = sqlSession.getConfiguration().getMappedStatement(sqlId).getSqlCommandType();
                if (sqlCommandType == SqlCommandType.INSERT) {
​
                }
                if (sqlCommandType == SqlCommandType.DELETE) {
​
                }
                if (sqlCommandType == SqlCommandType.UPDATE) {
                    methodCode.append("return sqlSession.update(\""+sqlId+"\", arg0);");
                }
                if (sqlCommandType == SqlCommandType.SELECT) {
                    String returnType = method.getReturnType().getName();
                    methodCode.append("return ("+returnType+")sqlSession.selectOne(\""+sqlId+"\", arg0);");
                }
​
                methodCode.append("}");
                CtMethod ctMethod = CtMethod.make(methodCode.toString(), ctClass);
                ctClass.addMethod(ctMethod);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
​
        // 创建对象
        Object obj = null;
        try {
            Class<?> clazz = ctClass.toClass();
            obj = clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
    }
}

修改AccountMapper.xml文件:namespace必须是dao接口的全限定名称,id必须是dao接口中的方法名

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--要想使用GenerateDaoProxy,namespace必须是dao的全限定名称-->
<mapper namespace="com.hhb.dao.AccountDao">
    <!--要想使用GenerdateDaoProxy,id必须是dao的方法名-->
    <select id="selectByActno" resultType="com.hhb.pojo.Account">
        select * from t_act where actno = #{actno}
    </select>
​
    <update id="updateByActno">
        update t_act set balance = #{balance} where actno = #{actno}
    </update>
</mapper>

修改service类中获取dao对象

[SSM]MyBatis使用javassist生成类和接口代理机制,mybatis,java,javaweb

七、MyBatis中接口代理机制及使用

7.1在之前的web应用中使用接口代理机制

将service中获取dao对象的代码修改

[SSM]MyBatis使用javassist生成类和接口代理机制,mybatis,java,javaweb 

前提:AccountMapper.xml文件中的namespace必须和dao接口的全限定名称一致,id必须和dao接口中方法名一致。否则报错提示如下:

[SSM]MyBatis使用javassist生成类和接口代理机制,mybatis,java,javaweb

 

7.2使用接口代理机制完成之前的CRUD(部分代码)

com.hhb.mapper.CarMapper

CarMapper相当于之前的CarDao。

package com.hhb.mapper;
​
import com.hhb.pojo.Car;
​
import java.util.List;
​
public interface CarMapper {
​
    int insert(Car car);
​
    int deleteById(Long id);
​
    int update(Car car);
​
    Car selectById(Long id);
​
    List<Car> selectAll();
}

测试文章来源地址https://www.toymoban.com/news/detail-523472.html

package com.hhb.test;
​
import com.hhb.mapper.CarMapper;
import com.hhb.pojo.Car;
import com.hhb.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
​
import java.util.List;
​
public class CarMapperTest {
    @Test
    public void testinsert() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        //面向接口获取接口的代理对象
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car = new Car(null, "4444", "奔驰cls300", 65.0, "2023-06-05", "燃油车");
        int count = mapper.insert(car);
        System.out.println(count);
        sqlSession.commit();
    }
​
    @Test
    public void testDeleteById() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        int count = mapper.deleteById(10L);
        System.out.println(count);
        sqlSession.commit();
    }
​
    @Test
    public void testUpdate() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car = new Car(28L, "1234", "奔驰cls300", 65.0, "2023-05-05", "燃油车");
        int count = mapper.update(car);
        System.out.println(count);
        sqlSession.commit();
    }
​
    @Test
    public void testSelectById() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car = mapper.selectById(1L);
        System.out.println(car);
        sqlSession.commit();
    }
​
    @Test
    public void testSelectAll() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> cars = mapper.selectAll();
        cars.forEach(car -> {
            System.out.println(car);
        });
    }
}
​

到了这里,关于[SSM]MyBatis使用javassist生成类和接口代理机制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • IDEA版SSM入门到实战(Maven+MyBatis+Spring+SpringMVC) -Maven使用前准备

    一.Maven准备 注意:IDEA2019.1.x 最高支持Maven的3.6.0 下载地址:http://maven.apache.org/ Maven底层使用Java语言编写的,所以需要配置JAVA_HOME环境变量及Path 将Maven解压 非中文无空格 目录下 配置 MAVEN_HOME 环境变量及 Path 新建系统变量MAVEN_HOME,添加变量值maven根目录 编辑系统变量Path,添

    2024年02月09日
    浏览(49)
  • Java笔记:使用javassist修改class文件内方法

    在工作突然有一个需求。线上运维的一个tomcat的web项目,运行的程序不正常。需要修改代码。可是这个项目代码非常的老,并且公司存储的源代码跟线上的不一致。 我了个擦,没有源代码但是还要结局客户的问题。只能到线上将对应程序的class文件拷贝到本地进行修改,每修

    2024年02月03日
    浏览(42)
  • 【SSM整合】对Spring、SpringMVC、MyBatis的整合,以及Bootstrap的使用,简单的新闻管理系统

    ✅作者简介:热爱Java后端开发的一名学习者,大家可以跟我一起讨论各种问题喔。 🍎个人主页:Hhzzy99 🍊个人信条:坚持就是胜利! 💞当前专栏:【Spring】 🥭本文内容:SSM框架的整合使用,还有bootstrap等前端框架的简单使用,做一个简单的新闻管理系统 在前文中,我们

    2024年02月06日
    浏览(46)
  • 【C#】当重复使用一段代码倒计时时,定义接口类和通过实现类继承接口方式进行封装方法和体现代码灵活性

    欢迎来到《小5讲堂》 大家好,我是全栈小5。 这是《C#》序列文章,每篇文章将以博主理解的角度展开讲解, 特别是针对知识点的概念进行叙说,大部分文章将会对这些概念进行实际例子验证,以此达到加深对知识点的理解和掌握。 温馨提示:博主能力有限,理解水平有限

    2024年01月19日
    浏览(44)
  • Mybatis-plus中IService接口的使用

    Mybatis-plus的IService接口:IService接口解释,我们可以看到IService接口就是有一大堆方法接口。 IService的使用: IService的使用需要另外两个接口的配合:baseMapper和ServiceImpl 第一步:实现basemapper接口 第二步:编写service类 第三步:编写serviceImpl,ServiceImpl里面是各种的方法实现,好

    2024年02月04日
    浏览(52)
  • 使用Mybatis生成树形菜单-适用于各种树形场景

    开发中我们难免会遇到各种树形结构展示的场景。比如用户登录系统后菜单的展示,某些大型购物网站商品的分类展示等等,反正开发中会遇到各种树形展示的功能,这些功能大概处理的思路都是一样的,所以本文就总结一下树形结构的代码生成,在开发的时候套用这种结构

    2024年02月08日
    浏览(37)
  • 使用Jmeter自带recorder代理服务器录制接口脚本

    脚本录制 配置线程组 添加代理服务器 端口 和 录制脚本放置位置可根据需要设置 启动录制 点击启动后 弹出创建证书提示,点击OK 这个证书后续需要使用到 然后可见 一个弹窗。 Recorder . 本质是代理服务+录制交易控制 可设置对应数据 方便录制脚本的查看 证书配置 Jmeter 证书

    2024年02月12日
    浏览(44)
  • 【JAVASE】抽象类和接口及其抽象类和接口的区别

    ✅作者简介:大家好,我是橘橙黄又青,一个想要与大家共同进步的男人😉😉 🍎个人主页:再无B~U~G-CSDN博客 目标: 1. 抽象类 2. 接口 3. Object 类 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的, 如果 一个类中

    2024年04月13日
    浏览(54)
  • SSM整合-Spring整合SringMVC、Mybatis,ssm测试

    ​ SSM(Spring + SpringMVC + Mybatis) 整合,就是三个框架协同开发。 Spring 整合 Mybatis,就是将 Mybatis 核心配置分拣当中数据源的配置、事务管理、工厂的配置、Mapper接口的实现类等 交给Spring进行管理。 mybatisConfig.xml配置信息 整合到 SpringConfig.xml Spring 整合 SpringMVC,就是在web.xml当中

    2023年04月22日
    浏览(52)
  • mybatis-generator代码生成器的使用与配置

    官网的MyBatis Generator使用介绍,请点击下面的链接: 链接 MyBatis Generator 生成的文件包含三类: (1)Model实体文件,一个数据库表对应生成一个 Model 实体; (2)Mapper接口文件,数据数操作方法都在此接口中定义; (3)Mapper XML配置文件 在pom.xml文件添加如下依赖: 代码如下

    2024年02月14日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包