mybatis 10 种设计模式
工厂模式 -> factory,建造者 -> builder
代理模式,创建复杂对象(非硬编码)所必须的,分静态和动态,一般用动态
装饰器,对原有的进行增强,比如一级缓存被包装,产生二级缓存
要定义标准流程,离不开模板模式,模板模式用抽象方法来定义一些标准流程
解决同一类问题时,因为一类下的问题也会有不同差异,所以使用策略模式
创建型模式
工厂模式
工厂模式负责延迟创建
sqlsession 的所有增删改查操作都是由执行器完成的,执行器只有 update 和 select 方法
单例模式
一般都会自己提供创建对象的过程,而不是依赖于其他框架(如 spring)
建造者模式
所有对象创建和 xml 解析基本上都是建造者模式创建的吗,一步一步构建复杂对象,而不是全部放到某个方法
结构型模式
适配器模式
代理模式
代理模式是很多框架的基石
代理模式在 mybatis 中将 configure 配置信息和 xml mapper 关联起来,并通过代理对象调用执行方法等
组合模式
将 sql 节点的解析过程串联起来,如果有新节点可以方便地扩展
装饰器模式
行为型模式
模板模式
常见,通常提供一个抽象类、base 基础类等定义一整套抽象方法,交给子类实现
策略模式
减少 if 判断
迭代器模式
将一个对象,有多少元素,然后继续拆解看子元素还有没有子元素,就是一个迭代的过程
创建简单的映射器代理工厂
package org.malred;
import com.sun.org.slf4j.internal.Logger;
import com.sun.org.slf4j.internal.LoggerFactory;
import org.junit.Test;
import org.malred.dao.IUserDao;
import org.malred.mybatis.binding.MapperProxyFactory;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
public class ApiTest {
@Test
public void test_MapperProxyFactory() {
MapperProxyFactory<IUserDao> factory = new MapperProxyFactory<>(IUserDao.class);
Map<String, String> sqlSession = new HashMap<>();
sqlSession.put("org.malred.dao.IUserDao.queryUserName",
"模拟执行 Mapper.xml 中的SQL语句,操作:查询用户名称");
IUserDao userDao = factory.newInstance(sqlSession);
String res = userDao.queryUserName("1");
System.out.println(res);
}
@Test
public void test_proxy_class() {
// jdk提供的代理
IUserDao userDao = (IUserDao) Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class[]{IUserDao.class},
((proxy, method, args) -> "你被代理了")
);
String res = userDao.queryUserName("1");
System.out.println(res);
}
}
package org.malred.dao;
public interface IUserDao {
String queryUserName(String uid);
Integer queryUserAge(String uid);
}
package org.malred.mybatis.binding;
import java.lang.reflect.Proxy;
import java.util.Map;
/**
* 映射器代理工厂
*/
public class MapperProxyFactory<T> {
// 被代理的接口
private final Class<T> mapperInterface;
public MapperProxyFactory(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
public T newInstance(Map<String, String> sqlSession) {
MapperProxy<T> mapperProxy = new MapperProxy<>(mapperInterface, sqlSession);
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(),
new Class[]{mapperInterface}, mapperProxy);
}
}
package org.malred.mybatis.binding;
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;
/**
* 映射器代理类
*/
public class MapperProxy<T> implements InvocationHandler, Serializable {
private static final Long serialVersionUID = -9646882346141251L;
private final Class<T> mapperInterface;
// 模拟存放的参数
private Map<String, String> sqlSession;
public MapperProxy(Class<T> mapperInterface, Map<String, String> sqlSession) {
this.mapperInterface = mapperInterface;
this.sqlSession = sqlSession;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// object提供的equals方法不应该被代理
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
} else {
return "你被代理了! " + sqlSession.get(mapperInterface.getName() + "." + method.getName());
}
}
}