一、问题说明
今天进行项目代码优化,将控制器的一些代码封装到组件中,以便于复用。
之前也经常将代码封装到@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的容器关系分析