spring,hibernate事务无效问题(由use-default-filters导致的事故)

来张图


spring,hibernate事务无效问题(由use-default-filters导致的事故)_第1张图片
图片发自App

前置

最近在开发一个web项目,集成hibernate,且使用了OpenSessionInViewFilter,发现spring的事务无效了。进行了如下配置:

spring上下文的applicationContext.xml

   
       
    




    




    
        
        
        
        
        
        
        
        
        
        
    



    
    







springmvc的上下文配置webApplicationContext.xml


    
    







    




    
        
            
            
                
                
                
            
        
    






    



一直以为是使用了OpenSessionInViewFilter这个类库的原因导致的失败,最后才发现是由于context:component-scan的use-default-filters导致的问题。

分析

  1. 会交给org.springframework.context.config.ContextNamespaceHandler处理;
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
  1. 的use-default-filters默认true,会交给ClassPathScanningCandidateComponentProvider进行扫描,看代码:
protected void registerDefaultFilters() {
    this.includeFilters.add(new AnnotationTypeFilter(Component.class));
    ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
    try {
        this.includeFilters.add(new AnnotationTypeFilter(
                ((Class) cl.loadClass("javax.annotation.ManagedBean")), false));
        logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
    }
    catch (ClassNotFoundException ex) {
        // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
    }
    try {
        this.includeFilters.add(new AnnotationTypeFilter(
                ((Class) cl.loadClass("javax.inject.Named")), false));
        logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
    }
    catch (ClassNotFoundException ex) {
        // JSR-330 API not available - simply skip.
    }
}

可以看到默认ClassPathBeanDefinitionScanner会自动注册对@Component、@ManagedBean、@Named注解的Bean进行扫描。如果细心,到此就找到问题根源了。

  1. 对exclude-filter,include-filter进行过滤
    首先通过exclude-filter 进行黑名单过滤;
    然后通过include-filter 进行白名单过滤;
    否则默认排除。

结论

 
     
     

那么这段代码不仅仅对@Controller的注解Bean进行了扫描,而且对@Compoent注解也扫描了,子注解@Service,@Repository也进行了扫描,所以原来mvc的上下文的Bean被后面的bean替换了。所以如下解决方法:

  1. 如果不需要默认的,则use-default-filters=“false”禁用掉。
  2. 直接写明具体Controller包名称。

你可能感兴趣的:(spring,hibernate事务无效问题(由use-default-filters导致的事故))