在上篇中,是接口类生成对应的映射器代理,再在代理中完成对应的接口调用。本篇中,提供包路径的扫描和注册,将注册生成的类与代理器对象插入进Map中,进行调用,并对session进行规范化处理。
注册器机制以及实现
注册器机制有两个方法,一个是获取对应的MapperProxyFactory对象,另一个是扫描对应的接口类,注册成MapperProxyFactory进行调用,这个注册器机制在以后的工程中可以去进行借鉴。
public class MapperRegistry {
/*
将映射代理添加到HashMap中
*/
private final Map<Class<?>, MapperProxyFactory<?>> mapperMap = new HashMap<>();
//相当于去进行重新获取
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) mapperMap.get(type);
if (mapperProxyFactory == null) {
throw new RuntimeException("原有的Mapper未包含对应资源,确认清楚");
}
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new RuntimeException("重新获取mapper时失败");
}
}
public void addMappers(String packageName) {
//从包中读出类
Set<Class<?>> classes = ClassScanner.scanPackage(packageName);
classes.stream().forEach(a ->
addMapper(a)
);
}
private void addMapper(Class<?> a) {
//只对接口生效
if (a.isInterface()) {
if (mapperMap.containsKey(a)) {
throw new RuntimeException("该接口已经扫描加载,再确定下机制是否存在问题");
}
mapperMap.put(a, new MapperProxyFactory<>(a));
}
}
}
addMappers是生成Map,getMapper是获取对应的接口代理器。
代理器工厂的实现
工厂实现还是按照一的实现去进行处理
public class MapperProxyFactory<T> {
private final Class<T> mapperInterface;
public MapperProxyFactory(Class<T> mapperInterface){
this.mapperInterface = mapperInterface;
}
public T newInstance(SqlSession sqlSession){
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface);
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, mapperProxy);
}
}
代理Mapper的实现
先上代码
public class MapperProxy<T> implements InvocationHandler, Serializable {
private static final long serialVersionUID = -6424540398559729838L;
private SqlSession sqlSession;
private Class<T> mapperInterface;
public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface){
this.sqlSession = sqlSession;
this.mapperInterface = mapperInterface;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (Object.class.equals(method.getDeclaringClass())){
return method.invoke(method, this);
}
return sqlSession.selectOne(method.getName(), args);
}
}
与一相比,对sqlSession进行对应的封装
sqlSession的封装与使用
接口封装——sqlSession与sqlSessionFactory的接口封装
public interface SqlSessionFactory {
/**
* 打开一个session
* @return
*/
SqlSession openSession();
}
/**
* 表示当前对象可以被关闭
*/
public interface SqlSession extends Closeable {
/**
* 根据指定的SqlId获取对应的封装对象
* @param statement
* @param <T>
* @return
*/
<T> T selectOne(String statement);
/**
* 根据指定的sqlId获取对应的封装对象,但允许向封装对象中塞入对应的参数
* @param statement
* @param parameter
* @param <T>
* @return
*/
<T> T selectOne(String statement, Object parameter);
/**
* 从session中获取对应的映射器
* @param type
* @param <T>
* @return
*/
<T> T getMapper(Class<T> type);
}
对sqlSession和sqlSeesionFactory进行实现
public class DefaultSqlSession implements SqlSession {
private MapperRegistry mapperRegistry;
public DefaultSqlSession(MapperRegistry mapperRegistry){ this.mapperRegistry = mapperRegistry;}
@Override
public <T> T selectOne(String statement) {
return (T) ("你被代理了" + statement);
}
@Override
public <T> T selectOne(String statement, Object parameter) {
return (T) ("你被代理了" + statement + "且输入的入参是" + parameter.toString());
}
/*
通过getMapper的映射,获取对应的映射mapper
*/
@Override
public <T> T getMapper(Class<T> type) {
return mapperRegistry.getMapper(type, this);
}
/*
close方法先作保留,看后期能否使用
*/
@Override
public void close() throws IOException {
}
}
public class DefaultSqlSessionFactory implements SqlSessionFactory {
private MapperRegistry mapperRegistry;
public DefaultSqlSessionFactory(MapperRegistry mapperRegistry){
this.mapperRegistry = mapperRegistry;
}
@Override
public SqlSession openSession() {
return new DefaultSqlSession(mapperRegistry);
}
}