Jrebel очищает перехватчики Mybatis при перезагрузке XML-файлов Mapper

Я использую Jrebel 6.3.0 для горячей перезагрузки XML Mapper Mybatis для моего загрузочного веб-приложения Spring. И я использовал конфигурацию 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 очищает перехватчики при перезагрузке 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;}");
  }
}

Можно ли как-то позволить Жребелю оставить себе перехватчики?


person John.Yuan    schedule 28.07.2016    source источник
comment
Нашли ли вы решение своей проблемы?   -  person patryk    schedule 25.08.2016
comment
Я не модифицировал jrebel, просто модифицировал один класс в mybatis. org.apache.ibatis.builder.xml.XMLMapperBuilder. В конце метода public void parse() { добавьте следующий код: // Добавлено yuanjinyong if (interceptors.size() == 0) { interceptors.addAll(configuration.getInterceptors()); } if (configuration.getInterceptors().size() == 0) { for (Перехватчик-перехватчик: перехватчики) { configuration.addInterceptor(перехватчик); } }   -  person John.Yuan    schedule 28.08.2016
comment
Вы изменили сам класс? Или, может быть, есть способ создать новый класс, расширяющий XMLMapperBuilder в вашем коде, и каким-то образом заменить тот, который использует mybatis, на тот, который вы написали?   -  person patryk    schedule 29.08.2016
comment
Мой проект представляет собой веб-приложение. Нам не нужно это изменение в prod-env, мы просто используем jrebel в dev-env, поэтому просто измените исходный файл, который извлекается из исходного jar, и поместите его в src/test/java, и он будет построен в каталоге классов и заменит класс в оригинальной банке. Не помещайте его в папку src/main/java.   -  person John.Yuan    schedule 31.08.2016


Ответы (1)


Мой проект представляет собой веб-приложение. Нам не нужно это изменение в prod-env, мы просто используем jrebel в dev-env, поэтому просто измените исходный файл, который извлекается из исходного jar, и поместите его в src/test/java, и он будет построен в каталоге классов и заменит класс в оригинальной банке. Не помещайте его в папку 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);
            }
        }
    }
...
}
person John.Yuan    schedule 31.08.2016