2016-07-28 2 views
1

Jrebel 6.3.0을 사용하여 Mybatis의 Mapper XML을 Spring 부트 웹 애플리케이션에 핫 리로드합니다. 그리고 Mybatis를 설정하기 위해 Java Configuration을 사용했습니다.Jrebel Mapper XML 파일을 다시로드 할 때 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; 
    } 

Jerbel이 매퍼 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이 인터셉터를 유지하기 위해 수 있도록 어쨌든이 있나요?

+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) { for (요격기 요격기 : 요격기) { configuration.addInterceptor (요격기); } } –

+0

클래스 자체를 수정 했습니까? 아니면 코드에 XMLMapperBuilder를 확장하고 mybatis가 사용하는 클래스로 대체하는 새로운 클래스를 만드는 방법이 있습니까? – patryk

답변

0

내 프로젝트는 웹 응용 프로그램입니다. 우리는 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); 
      } 
     } 
    } 
... 
}