当重新加载Mapper XML文件时,Jrebel清除Mybatis拦截器

时间:2016-07-28 10:11:38

标签: mybatis jrebel

我正在使用Jrebel 6.3.0为我的Spring启动Web应用程序热重载Mybatis的Mapper XML。我使用Java配置来配置Mybatis。

@Configuration
@ConditionalOnClass({ PageInterceptor.class })
@EnableConfigurationProperties(MybatisPageProperties.class)
@AutoConfigureBefore(MybatisAutoConfiguration.class)
public class MyBatisPageAutoConfiguration implements ApplicationContextAware {
    private static final Logger LOG = LoggerFactory.getLogger(MyBatisPageAutoConfiguration.class);

    @Autowired
    private MybatisPageProperties properties;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        BeanUtil.setApplicationContext(applicationContext);
    }

    /**
     * 
     * 
     * @return
     */
    @Bean
    public PageInterceptor pageInterceptor() {
        LOG.info("========PageInterceptor========");
        PageInterceptor pageInterceptor = new PageInterceptor();

        Properties p = new Properties();
        p.setProperty("dialect", properties.getDialect());
        p.setProperty("sqlIdRegex", properties.getSqlIdRegex());
        pageInterceptor.setProperties(p);

        return pageInterceptor;
    }

我发现Jrebel在重新加载mapper xml文件时会清除拦截器。

org.zeroturnaround.jrebel.mybatis.SqlMapReloader

  private void reconfigure() {
    log.infoEcho("Reloading SQL maps");

    this.conf.reinit(); // Clear loadedResources and interceptors

    reloadedResources.set(Collections.synchronizedSet(new HashSet()));
    enterReloading();
    try {
      if (this.confBuilder != null)
        this.confBuilder.reinit();
      reconfigureAdditionalMappings();


      exitReloading();
      reloadedResources.remove();
    }
    finally
    {
      exitReloading();
      reloadedResources.remove();
    }
  }

  .........

  private void reconfigureAdditionalMappings() {
    for (ResourceDesc rd : (ResourceDesc[])this.additionalMappings.toArray(new ResourceDesc[0])) {
      reconfigureMapping(rd);
    }
  }

  private void reconfigureMapping(ResourceDesc rd) {
    org.apache.ibatis.session.Configuration c = (org.apache.ibatis.session.Configuration)this.conf;
    try { // Only reload loadedResources from Mapper XML files.
      XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(ResourceUtil.asInputStream(rd.url), c, rd.path, c.getSqlFragments());

      xmlMapperBuilder.parse();
    }
    catch (Exception e) {
      if ((e.getCause() instanceof java.io.FileNotFoundException)) removeMappingForDeletedResource(rd); else {
        throw new RuntimeException("Failed to parse mapping resource: '" + rd.url + "'", e);
      }
    } finally {
      ErrorContext.instance().reset();
    }
  }

org.zeroturnaround.jrebel.mybatis.cbp.ConfigurationCBP

public class ConfigurationCBP
  extends JavassistClassBytecodeProcessor
{
  public void process(ClassPool cp, ClassLoader cl, CtClass ctClass)
    throws Exception
  {
    ctClass.addInterface(cp.get(JrConfiguration.class.getName()));

    ctClass.addField(new CtField(cp.get(SqlMapReloader.class.getName()), "reloader", ctClass));

    CtConstructor[] constructors = ctClass.getConstructors();
    for (int i = 0; i < constructors.length; i++) {
      CtConstructor constructor = constructors[i];
      if (constructor.callsSuper()) {
        constructor.insertAfter("reloader = new " + SqlMapReloader.class.getName() + "($0);");
      }
    }

    ctClass.addMethod(CtNewMethod.make("public " + SqlMapReloader.class
      .getName() + " getReloader() {" + "  return reloader;" + "}", ctClass));




    ctClass.addMethod(CtNewMethod.make("public void reinit() {  loadedResources.clear();  ((" + JrInterceptorChain.class


      .getName() + ") interceptorChain).jrClear();" + "}", ctClass));



    ctClass.getDeclaredMethod("isResourceLoaded").insertAfter("if (reloader.doReload($1)) {  loadedResources.remove($1);  $_ = false;}");
  }
}

有没有让Jrebel保留拦截器?

1 个答案:

答案 0 :(得分:0)

我的项目是web应用程序,我们不需要在prod-env中进行此更改,我们只需在dev-env中使用jrebel,所以只需修改从源jar获取的源文件,并将其放在src / test中/ java,它将构建到类dir,并替换原始jar中的类。不要将它放在src / main / java文件夹中。

org.apache.ibatis.builder.xml.XMLMapperBuilder

...
public class XMLMapperBuilder extends BaseBuilder {
    private static List<Interceptor> interceptors = new ArrayList<Interceptor>(); // Added by yuanjinyong
...
    public void parse() {
...
        parsePendingStatements();

        // Added by yuanjinyong
        if (interceptors.size() == 0) {
            interceptors.addAll(configuration.getInterceptors());
        }
        if (configuration.getInterceptors().size() == 0) {
            for (Interceptor interceptor : interceptors) {
                configuration.addInterceptor(interceptor);
            }
        }
    }
...
}