解决@Component组件使用@Value失败的问题

一、问题说明

今天进行项目代码优化,将控制器的一些代码封装到组件中,以便于复用。

之前也经常将代码封装到@Component注解的类中,因为有需要调用properties文件的部分。

出现了在@Component的类中,@Value("${xxxx}")无法调用properties文件值的问题。

问题出在哪里呢?

@Component
public class TestComponent {
    @Value("${test.index}")
    private String testIndex;

二、@Value("${}")@Value("#{}")的区别

参考资料
@Value(“#{}”)与@Value(“${}”)的区别

1、@Value("${}")
通过@Value(“${}”) 可以获取对应属性文件中定义的属性值。

2、@Value("#{}")
表示SpEl表达式通常用来获取bean的属性,或者调用bean的某个方法。当然还有可以表示常量

当bean通过@Value(#{“”}) 获取其他bean的属性,或者调用其他bean的方法时,只要该bean (Beab_A)能够访问到被调用的bean(Beab_B),即要么Beab_A 和Beab_B在同一个容器中,或者Beab_B所在容器是Beab_A所在容器的父容器。

三、配置文件比较

1、springmvc.xml

<!-- Spring容器采用反射扫描的发现机制,
Spring容器仅允许最多定义一个PropertyPlaceholderConfigurer 或 <content:property-placeholder>其余的会被Spring忽略 -->
<context:property-placeholder location="classpath:resources.properties,classpath:config.properties" ignore-unresolvable="true"/>

<!-- Spring加载全部bean,springMVC加载Controller -->
<!-- SpringMVC容器配置,让其只扫描包括@controller的Bean -->
<context:component-scan base-package="com.bisa.**.controller" use-default-filters="false">
   <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
   <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>

springmvc.xml配置文件,可以看到,只扫描controller注解的java类,因此,在这里只有@Controller的类能使用@Value(“${}”)获得properties文件中的内容。

2、spring.xml
作为父容器,是注册除了controller的所有bean的。
在spring.xml里,需要单独注入配置文件到bean。

<!-- Spring容器配置,排除所有@controller的Bean -->
    <!-- 扫描注解Bean -->
    <context:component-scan base-package="com.bisa">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

    <!-- 注入config.properties -->
    <bean id="prop" class="org.springframework.beans.factory.config.PropertiesFactoryBean">  
        <property name="locations">
            <array>  
                <value>classpath:config.properties</value>  
            </array>  
        </property>  
    </bean> 

这时候,就可以在@Component使用注解来获取配置文件的值了。
注意这里注入配置文件的id为”prop”,因此在使用注解时,需要用prop.xxxx来指明使用哪个配置文件的值。

@Component
public class TestComponent {
    @Value("#{prop.test.index}")
    private String testIndex;

关于spring.xml和springmvc.xml都要配置包扫描的疑问,可以参考资料
为啥Spring和Spring MVC包扫描要分开?
原理:
Spring 是父容器, Spring MVC是子容器, 子容器可以访问父容器的bean,父容器不能访问子容器的bean。
具体参照:
Spring和SpringMVC父子容器关系初窥
Spring为什么不做全局包扫描
Spring与SpringMVC的容器关系分析

猜你喜欢

转载自blog.csdn.net/misseel/article/details/80488123