Mybatis之核心主件分析

5 篇文章 0 订阅
3 篇文章 0 订阅

1、获取创建SqlSession的工厂类SqlSessionFactory

自动装配类MybatisAutoConfiguration的作用:

  1. 利用DataSourceAutoConfiguration引入合适的dataSource。
  2. 借助SqlSessionFactoryBean创建SqlSession的工厂类之DefaultSqlSessionFactory
  3. 创建SqlSessionTemplate,其中该模板类是对SqlSession做jdk代理。

DefaultSqlSessionFactory实例化之前SqlSessionFactoryBean内部优先实例化Configuration、解析自定义的xml文件等,如下所示:

public class SqlSessionFactoryBean{

    private Resource[] mapperLocations;
    private DataSource dataSource;
    private Configuration configuration;

    protected SqlSessionFactory buildSqlSessionFactory() throws Exception {
        final Configuration targetConfiguration = new Configuration();
        ...
        Stream.of(this.plugins).forEach(plugin -> {targetConfiguration.addInterceptor(plugin);});
        ...
        SpringManagedTransactionFactory smtf = new SpringManagedTransactionFactory();
        Environment e = new Environment(environment,transactionFactory == null ? smtf : transactionFactory,dataSource)
        targetConfiguration.setEnvironment(e);
        InputStream is = mapperLocation.getInputStream();
        Map<String, XNode> sqlFragments= targetConfiguration.getSqlFragments();
        XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(is,targetConfiguration, mapperLocation,sqlFragments);
        xmlMapperBuilder.parse();
        return new DefaultSqlSessionFactory(targetConfiguration);
      }
}
public class SqlSessionTemplate implements SqlSession, DisposableBean {

	public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
	    													PersistenceExceptionTranslator exceptionTranslator) {
	  ...
	  // 对DefaultSqlSession的代理
	  this.sqlSessionProxy = (SqlSession) newProxyInstance(cl,new Class[] { SqlSession.class }, si);
	}
	
	@Override
	public <T> T getMapper(Class<T> type) {
		//从SqlSessionFactory工厂类中获取Configuration
		return getConfiguration().getMapper(type, this);
	}
}

2、Mapper类型的接口实例化

@MapperScan引入ImportBeanDefinitionRegistrar类型的MapperScannerRegistrar,这也是Spring在解析@Import注解时涉及的一种类型。

public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    	  String className = MapperScan.class.getName()
    	  Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(className);
	      AnnotationAttributes mapperScanAttrs = AnnotationAttributes.fromMap(annotationAttributes);
	      if (mapperScanAttrs != null) {
	        registerBeanDefinitions(mapperScanAttrs, registry, generateBaseBeanName(importingClassMetadata, 0));
	      }
    }

    void registerBeanDefinitions(AnnotationAttributes annoAttrs, BeanDefinitionRegistry registry, String beanName) {
	      BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);
	      ...//解析@MapperScan相关属性,并赋值给MapperScannerConfigurer中相关属性
	      List<String> basePackages = new ArrayList<>();
	      basePackages.addAll(Arrays.stream(annoAttrs.getStringArray("basePackages")).filter(StringUtils::hasText)
       	 				.collect(Collectors.toList()));
       	  builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(basePackages));
	      registry.registerBeanDefinition(beanName, builder.getBeanDefinition());
    }
}

引入的核心类MapperScannerConfigurerBeanDefinitionRegistryPostProcessor类型的后置处理器。在此后置处理器内部会扫描@MapperScan配置路径下全部的Mapper接口。每个接口对应BeanDefinitionHolder其class类型均为MapperFactoryBean

2.1.创建Mapper接口的BeanDefinition

扫描@MapperScan所指定路径下所有的mapper接口,为每个接口创建其对应的BeanDefinition,其中Class属性为 MapperFactoryBean

MapperFactoryBean的抽象类SqlSessionDaoSupport存在类型为SqlSessionTemplate的属性,所以在每个BeanDefinition中都会指定SqlSessionTemplate赋值的方式。

如果没有注解@MapperScan显式指定SqlSessionTemplate的bean Name,默认情况选择AbstractBeanDefinition.AUTOWIRE_BY_TYPE方式属性赋值。

public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean{

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {

        ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
        scanner.setAddToConfig(this.addToConfig);
        ...
        String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
        scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, CONFIG_LOCATION_DELIMITERS));
    }

}
public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner {

   private Class<? extends MapperFactoryBean> mapperFactoryBeanClass = MapperFactoryBean.class;
   
    @Override
    public Set<BeanDefinitionHolder> doScan(String... basePackages) {
        // 扫描@MapperScan指定路径下的mapper接口
        Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
        if (beanDefinitions.isEmpty()) {
        } else {
          // 设置目标扫描bean对应Class属性为 MapperFactoryBean
          processBeanDefinitions(beanDefinitions);
        }
        return beanDefinitions;
    }

    private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
        GenericBeanDefinition definition;
        for (BeanDefinitionHolder holder : beanDefinitions) {
            definition = (GenericBeanDefinition) holder.getBeanDefinition();
            ...
            definition.setBeanClass(this.mapperFactoryBeanClass);
            definition.getPropertyValues().add("addToConfig", this.addToConfig);
            boolean explicitFactoryUsed = false;
            //如果@MapperScan指定了 sqlSessionFactoryRef
            if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
              RuntimeBeanReference r = new RuntimeBeanReference(this.sqlSessionFactoryBeanName);
              definition.getPropertyValues().add("sqlSessionFactory",r);
              explicitFactoryUsed = true;
            } else if (this.sqlSessionFactory != null) {
                definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);
                explicitFactoryUsed = true;
            }
            //如果@MapperScan指定了 sqlSessionTemplateBeanName
            if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
                RuntimeBeanReference r = new RuntimeBeanReference(this.sqlSessionTemplateBeanName);
                definition.getPropertyValues().add("sqlSessionTemplate",r);
                explicitFactoryUsed = true;
            } else if (this.sqlSessionTemplate != null) {
                definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
                explicitFactoryUsed = true;
            }
            //如果@MapperScan没有指定sqlSessionTemplateBeanName,则利用@Autowired功能注入
            if (!explicitFactoryUsed) {
                definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
            }
        }
    }
}

3、每个Mapper接口生成代理

public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {
  
    @Override
    public T getObject() throws Exception {
        // 从父类SqlSessionDaoSupport中获取SqlSession之SqlSessionTemplate
        return getSqlSession().getMapper(this.mapperInterface);
    }
}

最终利用工厂类MapperProxyFactory完成对目标接口的JDK代理。

public class MapperProxyFactory<T> {

	protected T newInstance(MapperProxy<T> mapperProxy) {
		ClassLoader cl = mapperInterface.getClassLoader();
    	return (T) Proxy.newProxyInstance(cl, new Class[] { mapperInterface }, mapperProxy);
  	}
	
	public T newInstance(SqlSession sqlSession) {
		// MapperProxy类型为InvocationHandler 
		//sqlSession即为SqlSessionDaoSupport中属性SqlSessionTemplate
    	final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
    	return newInstance(mapperProxy);
  	}
}

至此,@MapperScan指定路径下的所有mapper接口在Spring IOC容器中都生成了class类型为MapperFactoryBean的代理bean。

4、代理目标接口中的目标方法

public class MapperProxy<T> implements InvocationHandler {
    // SqlSessionDaoSupport中属性SqlSessionTemplate
    private final SqlSession sqlSession;

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        ...
        final MapperMethod mapperMethod = cachedMapperMethod(method);
        return mapperMethod.execute(sqlSession, args);
    }
}

3、SqlSession

  • 针对Springboot中,其子类包括SqlSessionTemplate、DefaultSqlSession。
  • 持有增删改查等基本api。以及辅助API「提交、关闭会话」。
  • 每个SQL请求都会创建一个SqlSession会话处理。

3.1、DefaultSqlSessionFactory

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
   final Environment environment = configuration.getEnvironment();
   //transactionFactory:SpringManagedTransactionFactory
   final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
   // tx = SpringManagedTransaction,并持有 DataSource
   tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
   // # 4.1
   final Executor executor = configuration.newExecutor(tx, execType);
   return new DefaultSqlSession(configuration, executor, autoCommit);
}

3.2、DefaultSqlSession

public class DefaultSqlSession implements SqlSession {

	public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
	  this.configuration = configuration;
	  this.executor = executor;
	  this.dirty = false;
	  this.autoCommit = autoCommit;
	}

	public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
    	MappedStatement ms = configuration.getMappedStatement(statement);
    	// #5.1:CacheExecutor#query
      	return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
  }
}

4、Configuration

4.1、创建Executor

public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
  executorType = executorType == null ? defaultExecutorType : executorType;
  executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
  Executor executor;
  if (ExecutorType.BATCH == executorType) {
    executor = new BatchExecutor(this, transaction);
  } else if (ExecutorType.REUSE == executorType) {
    executor = new ReuseExecutor(this, transaction);
  } else {
  	// transaction:SpringManagedTransaction
  	// this:Configuration
  	// #5.2
    executor = new SimpleExecutor(this, transaction);
  }
  if (cacheEnabled) {//默认为true
    // #5.1:CachingExecutor 持有真正执行SQL功能的SimpleExecutor
    executor = new CachingExecutor(executor);
  }
  // #9 【初始化 Executor 相关的拦截器插件】
  executor = (Executor) interceptorChain.pluginAll(executor);
  return executor;
}

5、Executor

5.1、CacheExecutor

// delegate:SimpleExecutor
public CachingExecutor(Executor delegate) {
  this.delegate = delegate;
  delegate.setExecutorWrapper(this);
}
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
  BoundSql boundSql = ms.getBoundSql(parameterObject);
  // 二级缓存key
  CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
  return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)throws SQLException {
  Cache cache = ms.getCache();
  if (cache != null) {
    flushCacheIfRequired(ms);
    if (ms.isUseCache() && resultHandler == null) {
      ensureNoOutParams(ms, boundSql);
      @SuppressWarnings("unchecked")
      List<E> list = (List<E>) tcm.getObject(cache, key);
      if (list == null) {
        list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
        tcm.putObject(cache, key, list); // issue #578 and #116
      }
      return list;
    }
  }
  //delegate 表示SimpleExecutor。SimpleExecutor是真正执行SQL功能,其对应的方法为doQuery或者doUpdate...
  //此处利用 模版 方式,调用的是抽象类BaseExecutor#query方法「BaseExecutor主要是处理一级缓存」
  return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}

5.2、SimpleExecutor

public SimpleExecutor(Configuration configuration, Transaction transaction) {
  // #5.3
  super(configuration, transaction);
}

5.2.1、初始化Connection

public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, 
BoundSql boundSql) throws SQLException {
   Configuration configuration = ms.getConfiguration();
   // #8.1 RoutingStatementHandler
   StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, 	
   boundSql);
   stmt = prepareStatement(handler, ms.getStatementLog());
   // RoutingStatementHandler#query
   return handler.query(stmt, resultHandler);
}
//handler:RoutingStatementHandler
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
  Statement stmt;
  // #7 通过 SpringManagedTransaction 获取 连接对象Connection
  Connection connection = getConnection(statementLog);
  // 如果 存在StatementHandler的插件,则调用 handler 为代理对象,直接调用 9.3、Plugin#invoke 【最终调用 PageInterceptors#intercept】,其中以 PageInterceptors 为例。
  // 执行 PageInterceptors#intercept 方法之后,最终执行到 #8.1 RoutingStatementHandler#prepare
  stmt = handler.prepare(connection, transaction.getTimeout());
  handler.parameterize(stmt);
  return stmt;
}

5.3、BaseExecutor

//transaction:SpringManagedTransaction
protected BaseExecutor(Configuration configuration, Transaction transaction) {
  this.transaction = transaction;
  this.configuration = configuration;
}

5.3.1、处理一级缓存localCache

public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
	  ...
	  List<E> list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
	  ...
	  return list;
}
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
	  List<E> list;
	  localCache.putObject(key, EXECUTION_PLACEHOLDER);
	  try {
	  	//#5.2~doQuery
	    list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
	  } finally {
	    localCache.removeObject(key);
	  }
	  localCache.putObject(key, list);
	  ...
	  return list;
}

6、 MappedStatement

public final class MappedStatement{
	private Configuration configuration;
	//net.ss.mapper.CommentDAO.query || net.ss.mapper.CommentDAO.save等
  	private String id;
  	private StatementType statementType;
    private ResultSetType resultSetType;
  	private SqlSource sqlSource;
  	private Cache cache;
  	private ParameterMap parameterMap;
  	private List<ResultMap> resultMaps;
}

基于 groovy + 注解方式分析。启动过程中处理所有的接口dao层。

public class Configuration {
	// type:表示dao层的接口,net.ss.mapper.CommentDAO
	public <T> void addMapper(Class<T> type) {
	  mapperRegistry.addMapper(type);
	}

	public <T> void addMapper(Class<T> type) {
		...
	    knownMappers.put(type, new MapperProxyFactory<>(type));//用于dao层接口实现动态代理
       	MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
        parser.parse();
        ...
    }
}
public class MapperAnnotationBuilder{

	public void parse() {
		Method[] methods = type.getMethods();
		for (Method method : methods) {
			parseStatement(method);
        }
	}

	void parseStatement(Method method) {
		...
		SqlSource sqlSource = getSqlSourceFromAnnotations(method, parameterTypeClass, languageDriver);
		//初始化 MappedStatement
		assistant.addMappedStatement(...)
	}
}
public class MapperBuilderAssistant extends BaseBuilder {
	public MappedStatement addMappedStatement(...){
		...
		MappedStatement statement = statementBuilder.build();
		// 由Configuration属性「Map<String, MappedStatement> mappedStatements」持有所有的MappedStatement
    	configuration.addMappedStatement(statement);
	}
}

6.1、SqlSource

BoundSql getBoundSql(Object parameterObject);

6.2、BoundSql

public class BoundSql {
	private final String sql;
  	private final List<ParameterMapping> parameterMappings;
  	private final Object parameterObject;
  	private final Map<String, Object> additionalParameters;
  	private final MetaObject metaParameters;

	public BoundSql(Configuration configuration, String sql, List<ParameterMapping> parameterMappings, Object 
		parameterObject) {
    this.sql = sql;
    this.parameterMappings = parameterMappings;
    this.parameterObject = parameterObject;
    this.additionalParameters = new HashMap<>();
    this.metaParameters = configuration.newMetaObject(additionalParameters);
  }
}

7、Connection

public abstract class BaseExecutor implements Executor{
	// 通过 SpringManagedTransaction 获取 连接Connection
	protected Connection getConnection(Log statementLog) throws SQLException {
	    Connection connection = transaction.getConnection();
	    if (statementLog.isDebugEnabled()) {
	      return ConnectionLogger.newInstance(connection, statementLog, queryStack);
	    } else {
	      return connection;
	    }
  	}
}
public class SpringManagedTransaction implements Transaction {
	
	private void openConnection() throws SQLException {
		// dataSource:HikariDataSource
	    this.connection = DataSourceUtils.getConnection(this.dataSource);
	    this.autoCommit = this.connection.getAutoCommit();
  }
}

8、StatementHandler

8.1、RoutingStatementHandler

public class Configuration {
	public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object 
	        parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
    	StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, 
                rowBounds, resultHandler, boundSql);
       // #9:【初始化 StatementHandler的拦截器插件】
    	statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
    return statementHandler;
  }
}

RoutingStatementHandler中代理的类都是继承至抽象类BaseStatementHandler的实现类。

public class RoutingStatementHandler implements StatementHandler {
  private final StatementHandler delegate;
  
  public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, 
  		ResultHandler resultHandler, BoundSql boundSql) {
    switch (ms.getStatementType()) {
      case STATEMENT:
        delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      case PREPARED:
        delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      case CALLABLE:
        delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
    }
  }

	@Override
	public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
	  // delegate:PreparedStatementHandler,根据模板模式,最终调用BaseStatementHandler#prepare
	  return delegate.prepare(connection, transactionTimeout);
	}

	@Override
	public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
	  //delegate:PreparedStatementHandler
	  return delegate.query(statement, resultHandler);
	}
}
public abstract class BaseStatementHandler implements StatementHandler {
	
	protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, 	
		RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
    this.configuration = mappedStatement.getConfiguration();
    this.executor = executor;
    this.mappedStatement = mappedStatement;
    this.rowBounds = rowBounds;
    this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
    this.objectFactory = configuration.getObjectFactory();
    if (boundSql == null) { // issue #435, get the key before calculating the statement
      generateKeys(parameterObject);
      boundSql = mappedStatement.getBoundSql(parameterObject);
    }
    this.boundSql = boundSql;
    // 初始化 ParameterHandler
    this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
    //初始化 ResultSetHandler
    this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, 
    	resultHandler, boundSql);
  }

	public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
		  ErrorContext.instance().sql(boundSql.getSql());
		  Statement statement = null;
		  try {
		    // 根据connection获取 HikariProxyPreparedStatement
		    statement = instantiateStatement(connection);
		    setStatementTimeout(statement, transactionTimeout);
		    setFetchSize(statement);
		    return statement;
		  }
	}
}

8.2、ParameterHandler

public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql{
    // DefaultParameterHandler
    ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, 
    	parameterObject, boundSql);
    // #9:【初始化 ParameterHandler的拦截器插件】
    parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
    return parameterHandler;
  }

8.3、ResultSetHandler

 public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, 
 	ParameterHandler parameterHandler,ResultHandler resultHandler, BoundSql boundSql) {
 	// DefaultResultSetHandler
    ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);
     // #9:【初始化 ResultSetHandler的拦截器插件】
    resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
    return resultSetHandler;
  }

8.4、PreparedStatementHandler

  @Override
  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
    PreparedStatement ps = (PreparedStatement) statement;
    // 最终执行原生jdbc对数据的操作
    ps.execute();
    //处理结果映射
    return resultSetHandler.handleResultSets(ps);
  }

9、拦截器拦截插件

9.1、InterceptorChain

public class InterceptorChain {
  //用户自定义的所有拦截器插件
  private final List<Interceptor> interceptors = new ArrayList<>();

  public Object pluginAll(Object target) {
    for (Interceptor interceptor : interceptors) {
      target = interceptor.plugin(target);
    }
    return target;
  }
}

9.2、PageInterceptors

以分页插件 PageInterceptors 为示例:

@Override
public Object plugin(Object target) {
    return Plugin.wrap(target,this);
}

9.3、Plugin

public class Plugin implements InvocationHandler {

  private final Object target;
  private final Interceptor interceptor;
  private final Map<Class<?>, Set<Method>> signatureMap;

  private Plugin(Object target, Interceptor interceptor, Map<Class<?>, Set<Method>> signatureMap) {
    this.target = target;
    this.interceptor = interceptor;
    this.signatureMap = signatureMap;
  }
  // target:拦截器插件类型,interceptor:自定义拦截器【PageInterceptors】
  public static Object wrap(Object target, Interceptor interceptor) {
    Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
    Class<?> type = target.getClass();
    Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
    if (interfaces.length > 0) {//如果当前type实现了拦截器,则通过jdk接口代理生成当前 type 的代理类
      return Proxy.newProxyInstance(
          type.getClassLoader(),
          interfaces,
          new Plugin(target, interceptor, signatureMap));
    }
    return target;
  }

  // 执行完
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
      Set<Method> methods = signatureMap.get(method.getDeclaringClass());
      if (methods != null && methods.contains(method)) {
        // interceptor 为自定义的 【PageInterceptors】
        return interceptor.intercept(new Invocation(target, method, args));
      }
      return method.invoke(target, args);
    } catch (Exception e) {
      throw ExceptionUtil.unwrapThrowable(e);
    }
  }
  // 具体解析 某个拦截器
  private static Map<Class<?>, Set<Method>> getSignatureMap(Interceptor interceptor) {
    // 获取 注解@Intercepts的内容
    Intercepts interceptsAnnotation = interceptor.getClass().getAnnotation(Intercepts.class);
    ...
    // 获取 注解@Intercepts中@Signature注解的 所有value属性
    Signature[] sigs = interceptsAnnotation.value();
    Map<Class<?>, Set<Method>> signatureMap = new HashMap<>();
    for (Signature sig : sigs) {
      //通过 @Signature 注解中配置的 method & args 确定当前type 下的具体的方法
      Set<Method> methods = signatureMap.computeIfAbsent(sig.type(), k -> new HashSet<>());
      Method method = sig.type().getMethod(sig.method(), sig.args());
      methods.add(method);
    }
    return signatureMap;
  }

  private static Class<?>[] getAllInterfaces(Class<?> type, Map<Class<?>, Set<Method>> signatureMap) {
    Set<Class<?>> interfaces = new HashSet<>();
    while (type != null) {
      // 获取当前 type 下所有的接口
      for (Class<?> c : type.getInterfaces()) {
        // 实现插件拦截器的intercept,并非是当前type
        if (signatureMap.containsKey(c)) {
          interfaces.add(c);
        }
      }
      type = type.getSuperclass();
    }
    return interfaces.toArray(new Class<?>[interfaces.size()]);
  }

}

SqlSession & Executor区别

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • CacheExecutor:处理二级缓存。
  • 抽象类BaseExecutor:负责处理基本功能&一级缓存。query & update 方法。
  • SimpleExecutor真正执行SQL功能。doQuery & doUpdate 方法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值