2016-07-28 7 views
1

Я использую Jrebel 6.3.0 для горячей перезагрузки XML-файла Mybatis для моего веб-приложения Spring. И я использовал конфигурацию Java для настройки Mybatis.Jrebel clear Перехватчики Mybatis при перезагрузке XML-файлы Mapper

@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-файла mapper.

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 держать перехватчики?

+0

Вы нашли любое решение вашей проблемы? – patryk

+1

Я не изменял 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) { для (перехватчик перехватчика: перехватчики) { configuration.addInterceptor (перехватчик); } } –

+0

Вы изменили сам класс? Или, может быть, есть способ создать новый класс, который расширяет XMLMapperBuilder в вашем коде и каким-то образом заменяет тот, который mybatis использует с тем, который вы написали? – patryk

ответ

0

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