创建一个简单的映射器代理工厂(pr怎么创建代理文件)

热爱学习,热爱生活!沉淀、分享、成长,让自己和他人都有所收获!当我们使用Mybatis时,我们会有这样一个问题:为什么Mybatis只需要定义一个接口,并且可以使用XML或注释中的SQL语句来完成对数据库的CRUD,而不需要编写

热爱学习,热爱生活!

沉淀、分享、成长,让自己和他人都有所收获!

我的介绍。

当我们使用Mybatis时,我们会遇到这样的问题:“为什么Mybatis只需要定义一个接口,并且可以使用XML或注释中的SQL语句来完成对数据库的CRUD,而不需要编写实现类?& # 8220;。在阅读了Mybatis的源代码后,我意识到Mybatis使用映射器接口代理类将所有数据库操作移交给代理类。

二、绑定模块

映射器接口代理类在绑定模块,核心类是org.apache.ibatis.binding.映射器代理绑定模块的核心类如下:

  • org.apach.ibatis.binding.映射器Registry映射器接口注册类,管理映射器接口类型及其代理创建工作的映射,这是我们在开发中创建的映射器接口类将在这里注册以进行管理。
  • org.apach.ibatis.binding.映射器代理Factory映射器接口代理类创建一个工厂类。
  • org.apach.ibatis.binding.映射器代理映射器接口代理类,封装SqlSession相关的运算,我们稍后会学到,是SQL实现。
  • org.apach.ibatis.binding.映射器Method:包映射器接口和对应的方法SQL执行信息,这是我们在开发过程中创建的映射器接口类的每个方法对应于XML配置SQL声明。

流程图如下:

3.设计

通常,如果您能找到每个人正在做的事情的共同内容,并拥有统一的流程,那么它就可以被浓缩和细化,打包成公共组件或服务,并由每个人共享,以减少无用工作的重复。

参考我们最常用的JDBC从获取数据库连接、查询、封装结果集到返回结果集的方法,这些步骤是固定的过程,因此我们可以将该过程封装到通用组件或服务中。

当我们设计一个蠕虫在构建框架的过程中,首先要考虑如何集成用户自定义的数据库操作接口,XML配置SQL语句和数据库链接在一起。实际上,最合适的操作是使用代理方法进行处理,因为代理可以将一个复杂的流程封装为接口对象的实现类,设计如下:

  • 首先提供一个文件夹接口代理类映射器Poxy,通过代理类包装数据的操作。目前,我们将在本章中首先提供一个简单的包装器来模拟对数据库的调用。
  • 然后映射器接口代理类提供了一个简单的工厂类映射器代理Factory转移实例每种方法映射器接口成为代理类。

4、实现

在实现之前,我们首先学习了代理知识。我们使用动态代理模式。我们经过一个小的演示要了解动态代理模式,还有另外两种代理模式:静态代理,格利布表演。

动态代理

动态代理具有以下特点:

  • 动态代理对象不需要实现接口,只有目标对象需要实现接口。
  • 实现基于接口的动态代理需要使用JDK中性应用程序接口,存在JVM内存内动态构造代理,在运行时有效。
  • 需要使用java.lang.reflect.代理和它的new代理Instance ()方法,此方法需要传入三个参数,源代码如下:

    @CallerSensitive
    public static Object new代理Instance(类加载器加载程序,
    Class<?>[] 接口,
    InvocationHandler h)
    throws IllegalArgumentException{
    //...
    }
    • 类加载器加载程序:指定当前目标对象使用的类加载。获取加载器的方法为getClassLoader ()
    • 接口:目标对象实现接口类型,并使用泛型方法确认接口类型。
    • InvocationHandler h:事件处理,当执行目标方法对象的方法时,将触发事件处理程序的方法,并将当前执行的目标对象的方法作为参数传入。

我们通过特定的实现在动态代理上执行操作。类结构图如下:

代码:

映射器接口代理类:

public class 映射器代理<T> implements InvocationHandler, Serializable {
private static final long serialVersionUID = -6424540398559729838L;
private Map<String, String> sqlSession;
private final Class<T> mapperInterface;
public 映射器代理(Map<String, String> sqlSession, Class<T> mapperInterface) {
这.sqlSession = sqlSession;
这.mapperInterface = mapperInterface;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (Object.class.equals(方法。getDeclaringClass())) {
//The method in Object, execute directly
return 方法。invoke(这, args);
} else {
return "class" + mapperInterface.getName() + "is proxied, and the method is executed: " + 方法。getName() +
" , sqlSession is: " + sqlSession;
}
}
}

映射器接口代理类创建一个工厂类:

public class 映射器代理Factory<T> {
/**
* 映射器 interface type
*/
private final Class<T> mapperInterface;
public 映射器代理Factory (Class<T> mapperInterface) {
这.mapperInterface = mapperInterface;
}
public T newInstance(Map<String, String> sqlSession) {
映射器代理 mapper代理 = new 映射器代理(sqlSession, mapperInterface);
return (T) 代理.new代理Instance(mapperInterface.getClassLoader (), new Class[]{mapperInterface}, mapper代理);
}
}

IUserDao类型:

public interface IUserDao {
String queryUserName(String uId);
}

测试类:

public class 映射器代理Test {
@Test
public void test() {
映射器代理Factory<IUserDao> factory = new 映射器代理Factory<IUserDao>(IUserDao.class);
Map<String, String> sqlSession = new HashMap<>();
sqlSession.put("cn.bugstack.mybatis.test.dao.IUserDao.queryUserName", "Simulate the operation of executing the SQL statement in 映射器.xml: query user name");
sqlSession.put("cn.bugstack.mybatis.test.dao.IUserDao.queryUserAge", "Simulate the operation of executing the SQL statement in 映射器.xml: query user age");
IUserDao userDao = factory.newInstance(sqlSession);
String res = userDao.queryUserName("1");
System.out.println(res);
}
}

测试结果如下:

The class qtspace.cn.binding.IUserDao is proxied, and the method is executed: queryUserName, and the sqlSession is: {cn.bugstack.mybatis.test.dao.IUserDao.queryUserAge=Simulate the operation of executing the SQL statement in 映射器.xml: query user age , cn.bugstack.mybatis.test.dao.IUserDao.queryUserName=Simulate the operation of executing the SQL statement in 映射器.xml: query user name}

从以上测试结果可以看出IUserDao已经被委派并正在执行映射器代理 #调用程序()当代理执行该方法时IUserDao # queryUserName ()方法。

必须注意的是:在动态代理的方式下,所有的方法都将通过调用程序()方法执行,但动态代理的问题是它只能代理实现某个接口的实现类,而代理类只能代理接口中实现的方法。如果实现类有自己的私有方法,但不在接口中,则不能委派此方法。

JAVA

使用JAD集成到Eclipse中,可以方便地查看任何Java类的源代码(怎样在eclipse中查看jar源码)

2023-1-18 13:28:44

JAVA

解析XML数据的方法是什么?(解析xml数据的方法是什么样的)

2023-1-18 13:30:25

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索