MyBatis提供了一個 interceptor
public interface Interceptor {
Object intercept(Invocation var1) throws Throwable;
Object plugin(Object var1); //注冊插件
void setProperties(Properties var1);
}
插件需要使用 Intercepts 注解, Signature 描述攔截的方法簽名, 如:
@Intercepts({@Signature(
type = Executor.class,
method = "query",
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
), @Signature(
type = Executor.class,
method = "query",
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}
)})
這里攔截 Executor的查詢方法[四個參數(shù)和六個參數(shù)].
MyBatis Mapper接口使用jdk動態(tài)代理 具體類為 MapperProxyFactory:
public class MapperProxyFactory<T> {
private final Class<T> mapperInterface;
private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap();
public MapperProxyFactory(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
public Class<T> getMapperInterface() {
return this.mapperInterface;
}
public Map<Method, MapperMethod> getMethodCache() {
return this.methodCache;
}
protected T newInstance(MapperProxy<T> mapperProxy) {
return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
MapperProxy mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache);
return this.newInstance(mapperProxy);
}
}
通過 MapperProxyFactory可以獲取具體的Mapper然后調(diào)用接口方法.執(zhí)行數(shù)據(jù)庫操作
流程為:
SqlSessionFactory得到 SqlSession 然后獲得 Configuration 然后 獲取Mapper :
public <T> T getMapper(Class<T> type) {
return this.configuration.getMapper(type, this);
}
//Configuration
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return this.mapperRegistry.getMapper(type, sqlSession);
}
//MapperRegistry
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
MapperProxyFactory mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
if(mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
} else {
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception var5) {
throw new BindingException("Error getting mapper instance. Cause: " + var5, var5);
}
}
}