☆相同Bean分别被Spring MVC子容器与Spring父容器初始化,导致@Value注入失败

1 问题描述

在车保养项目开发过程中,技术架构:Spring MVC + MyBatis;Service层接口中属性,如果使用注解@Value注入,不能够拿到Properties文件中拿到对应的key值;但在Spring配置文件applicationContext-xxx.xml文件中配置的Properties就可以拿到。具体项目中相关代码如下:

Spring MVC的dispatcher-servlet.xml文件




    
    
        
        
            
                
            
        
    

    
    
    

    
    

    
    

    
    
    
    

    
        
        
        
    

    
    
        
        
        
        
    

    
    
        
            
            
            
            
            
            
        
        
            
            
            
            
            
            
        
    

    
    

Spring的applicationContext-service.xml文件




    
    
    

    
    

    
    

    
    
        
            
            
            
            
            
            
            
            

            
            
            
            
            
        
    

    
    
        
        
    

    
    

    
    
        
            
                
                    
                        ${server_1}
                    
                    
                        ${port_1}
                    
                
            
        
        
            
                ${priority_1}
            
        
        
        
            
        
        
            
        
        
            
        
    

    
        
    

    
        
        
        
        
        
    

Service层OrderServiceImpl的代码

    public class OrderServiceImpl implements OrderService {
    
        @Value("${bopai.provider_id}")
        private String bopaiProviderId;

        @Value("${bopai.provider_name}")
        private String bopaiProviderName;

        @Value("${bopai.connect.phone}")
        private String boPaiPhone;

        ......
    }

2 排查过程

  1. Spring的applicationContext-service.xml文件配置的属性,可以正常拿到Properties文件中的值;【正常】
  2. 项目工程的Service层OrderServiceImpl实现,@Value不能拿到Properties文件中的值;【不正常】
  3. 代码断点调试:发现OrderServiceImpl被初始化了两次,第一次@Value可以拿到值,第二次@Value没有拿到值;【不正常】
  4. 发现根本原因:Spring 容器和Spring MVC容器分别都初始化了Service的实例,后者第二次初始化Service实例时,没有拿到@Value值,该实例覆盖掉了Spring 容器初始化的实例;

3 解决方案

通过修改两个配置文件的扫包范围,达到以下效果:

  1. Spring MVC的配置文件dispatcher-servlet严格限制只初始化Controller层实例;
  2. Spring的配置文件applicationContext-service.xml严格限制只初始化除Controller层的其他层实例;

修改后的配置文件:

  1. Spring MVC的dispatcher-servlet.xml文件



    
    
        
        
            
                
            
        
    

    
    
    

    
    

    
    

    
    
    
    

    
        
        
        
    

    
    
        
        
        
        
    

    
    
        
            
            
            
            
            
            
        
        
            
            
            
            
            
            
        
    

    
    

  1. Spring的applicationContext-service.xml文件



    
    
    

    
    

    
    

    
    
        
            
            
            
            
            
            
            
            

            
            
            
            
            
        
    

    
    
        
        
    

    
    

    
    
        
            
                
                    
                        ${server_1}
                    
                    
                        ${port_1}
                    
                
            
        
        
            
                ${priority_1}
            
        
        
        
            
        
        
            
        
        
            
        
    

    
        
    

    
        
        
        
        
        
    

4 问题总结

Spring MVC容器是Spring容器的一个子容器,它同样能够初始化实体类。由于SpringMVC容器的初始化是在Spring容器初始化之后,所以它会替换Spring中已经存在的类,这样可能会导致冲突。因此在Spring的配置文件中SpringMVC和Spring容器各司其职,在使用ComponentScan进行扫描时,各自扫描各自的实体类。如下配置:

  1. Spring容器扫描配置
    
                 
    
  1. SpringMVC容器扫描配置
    
        
        
    

以上配置在使用Spring xml-based配置时是没有问题的。如果在项目中引入java-base配置时,同时引入了@Configuration注解,@Configuration注解是在Spring容器初始化时进行实体类的初始化工作,因此在Spring MVC扫描配置中要将其过滤掉,否则会导致SpringMVC 的rest地址不可访问的问题。新的配置如下:

    
        
        
        
        
    

你可能感兴趣的:(☆相同Bean分别被Spring MVC子容器与Spring父容器初始化,导致@Value注入失败)