日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無先后,達(dá)者為師

網(wǎng)站首頁 編程語言 正文

mybatis的相同攔截器—切面執(zhí)行的順序

作者:LiZhen798 更新時(shí)間: 2022-07-16 編程語言

結(jié)論:攔截同一個(gè)方法的攔截器和我們?cè)趍ybatis-config.xml文件中的順序相反

1. plugin生效的兩種方式

推薦閱讀——plugin生效的方式

源碼位置:mybatis的自動(dòng)加載:org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration#sqlSessionFactory

public class MybatisAutoConfiguration {

  private static Log log = LogFactory.getLog(MybatisAutoConfiguration.class);
  //讀取Spring容器中的所有的plugin插件
  @Autowired(required = false)
  private Interceptor[] interceptors;
  @Bean
  @ConditionalOnMissingBean
  public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
    SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
    factory.setDataSource(dataSource);
    factory.setVfs(SpringBootVFS.class);
    if (StringUtils.hasText(this.properties.getConfigLocation())) {
      //讀取mybatis-config.xml的地址
      factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
    }
    factory.setConfiguration(properties.getConfiguration());
    //放入插件
    if (!ObjectUtils.isEmpty(this.interceptors)) {
      factory.setPlugins(this.interceptors);
    }
    if (this.databaseIdProvider != null) {
      factory.setDatabaseIdProvider(this.databaseIdProvider);
    }
    if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {
      factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
    }
    if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {
      factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
    }
    if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
      factory.setMapperLocations(this.properties.resolveMapperLocations());
    }

    return factory.getObject();
  }
}

注意:SqlSessionFactoryBean實(shí)現(xiàn)了InitializingBean接口,在afterPropertiesSet()方法中將執(zhí)行org.mybatis.spring.SqlSessionFactoryBean#buildSqlSessionFactory方法去讀取ConfigLocation的xml文件,解析plugin并放入集合中。

結(jié)論:spring容器的plugin先放入到集合中,后續(xù)將mybatis-config.xml的plugin按先后順序放入到集合中。

2. plugin切面執(zhí)行的順序

源碼位置:org.apache.ibatis.plugin.InterceptorChain該方法會(huì)對(duì)target代理,并且對(duì)代理類在進(jìn)行代理。一層一層的增強(qiáng)target類,故越靠后的Interceptor越先執(zhí)行。

public class InterceptorChain {

  private final List<Interceptor> interceptors = new ArrayList<Interceptor>();

  public Object pluginAll(Object target) {
    //將項(xiàng)目啟動(dòng)時(shí)注冊(cè)的interceptors拿出來,執(zhí)行plugin方法。
    for (Interceptor interceptor : interceptors) {
      target = interceptor.plugin(target);
    }
    return target;
  }

  public void addInterceptor(Interceptor interceptor) {
    interceptors.add(interceptor);
  }
  
  public List<Interceptor> getInterceptors() {
    return Collections.unmodifiableList(interceptors);
  }

}

而plugin方法:

@Slf4j
@Intercepts(
        @Signature(type = Executor.class, method = "query", args = {
                MappedStatement.class, Object.class, RowBounds.class,
                ResultHandler.class }))
public class A1Interceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        log.info("A1 before...");
        Object proceed = invocation.proceed();
        log.info("A1 after...");
        return proceed;
    }

    /**
     * 將插件對(duì)象加入到攔截器鏈中
     * @param target
     * @return
     */
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }
}

實(shí)際上會(huì)調(diào)用Plugin.wrap(target, this)方法。

  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) {
      return Proxy.newProxyInstance(
          type.getClassLoader(),
          interfaces,
          new Plugin(target, interceptor, signatureMap));
    }
    return target;
  }

wrap方法會(huì)創(chuàng)建代理對(duì)象。

代理對(duì)象.png

wrapper()方法對(duì)target對(duì)象一層一層的代理。即before切面執(zhí)行的順序與放入plugins的順序相反。

原文鏈接:https://blog.csdn.net/LiZhen314/article/details/125760408

欄目分類
最近更新