为什么春天@Value与@Controller不兼容?(Why is Spring @Value i

2019-06-23 13:28发布

我在寻找一个更好的理解这个问题。 一种解决方法是相当简单,即配置数据移动到另一个类,不具有代理/咨询缠着,但我觉得这个理解会更好地帮助我避免在未来的其他相关问题,所以我想任何人解释可以提供。

我使用的是春天STS和TC的vFabric服务器春季3.1.0.RELEASE。 实施使用@Controller类基本没什么REST服务器。 这是所有伟大的(实际上,它是),但@Controller也@Transactional,并且和负载时编织和TC的vFabric服务器之间,它打破@Value。

@Controller
@RequestMapping("/hello")
public class MyAPI {

    @Value("${my.property}")
    private String prop;
    ...

    @Transactional
    handleRequest(...) ...


}

和属性文件app.properties:

my.property = SUCCESS

这JUnit的下正常工作,与测试越来越有支撑设置为“成功”一MyAPI对象。 但是,当应用程序被加载到的vFabric,我猜它会加载时间编织和代理。 无论发生什么事情,有创造了两个MyAPI情况下,一个拥有道具==“成功”和另一个(这是很不幸的是处理HTTP请求中的一个),其中有托==“$ {} my.prop”。

因此,所有功能于所有我把这种魔法失效,这是我使用的东西像AOP最关心的问题。 即使STS我不知道如何追查是什么问题背后的原因或计算出,如果这是一个严重的错误。 如果它是一个错误,我不知道它是否是在春天,AspectJ的,在加载时织,或的vFabric一个错误,所以我甚至不知道从哪里发送错误报告。

因此,在理解这个任何帮助,将不胜感激。 谢谢。

Answer 1:

我想到了。 说真的,太多的魔力。

我用Spring Roo的STS中产生的基本应用程序框架,然后用STS,因为我们不想坚持下去分解出来袋鼠。

有一件事袋鼠做的“最佳实践”是创建两个Spring上下文的,一个是整个应用程序,以及一个有限的调度的servlet。 究竟为什么,我仍然没有得到,但我猜他们想保持在表示层的东西,如控制器,从爬行到被共享的服务层。 这是很好的axtavt解释这里 。 这是全部由我通过STS隐藏。

在与小豆STS的WEB-INF源是不是我期望它,在/ src目录/主/资源(这是在META-INF目录),但在替代/ src目录/主/ web应用程序,这是不是Java源目录并因此示出完全分开,只是/目标目录的上方,所以我误以为它用于输出文件夹。

在applicationContext.xml,袋鼠已经插入了过滤器,以防止从构建控制器应用程序上下文,在axtavt的职位说明,但也存在另一种过滤器,以消除扫描袋鼠生成的类。 我花了两个过滤器出来的同时,并不真正了解他们有什么,但认为他们只是Roo的剩菜。

所以,现在我已经得到了的问题, 正在创建的两倍控制器如前所述。 而一个在应用程序上下文获得分配的属性,因为它使用的applicationContext.xml并找到属性文件。 但是,为什么没有他们俩获得的属性设置?

这让我回模糊的webapps目录。 内的WEB-INF文件夹小豆已经放置了web.xml(天然地)和含有webmvc-config.xml文件的弹簧夹。 这个配置文件被设置为扫描,创建和建立公正的控制器。 web.xml文件建立Web应用程序使用的applicationContext.xml和DispatcherServlet的使用webmvc-config.xml文件,所以我应该离开在applicationContext.xml过滤器,以避免双重创作。

拼图的最后一块是这样的webmvc-config.xml文件。 自认为是其中的控制器设置地图的背景下,有<背景:物业占位符/>需要文件配置,以及使之能找到的属性文件。



Answer 2:

首先,使用$符号是正确的,而不是#

现在,关于原来的海报,我认为你有2个注释(@Controller和@Transactional)之间冲突的行为。

使用@Transactional注解将proxify你的实现(我猜检测到错误并启动回滚)。

现在你说你看到你的控制器的两个实例。 这是不应该的。 通常情况下,你应该只在内存中加载一个控制器的一个实例。

可能与你的配置文件或由于@Transactional的存在和其代理的性质?

作为一个方面说明,我从来没有在控制器使用@Transactional自己,但无论是在服务或DAO的方法。 由于后者可能无法和需要还原至实际过程是存在的,并且可以是从不同的控制器/源接入。

问候。



Answer 3:

我有同样的问题,这是我需要两个事实

为了得到这两个senarios工作

  1. 注入的属性(经由@Value)到一个控制器
  2. 注入一个managed bean(通过@Inject),该属性哈桑(经由@Value)到控制器

我希望这有帮助。

下面是web.xml中。

    <servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/spring-config/spring-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

这里是为spring-servlet.xml:关键是要兼得UTIL:属性和背景:物业占位符。 虽然他们找到相同的文件,他们的目的不同。

<util:properties id="propSource" location="classpath:/properties/prop1.properties" />
<context:property-placeholder location="classpath:/properties/prop1.properties" />

<context:component-scan base-package="com.concurrent.controller" />

<context:annotation-config/>
<mvc:annotation-driven/> 

这里是我的控制器类的一个片段:

@Controller
@RequestMapping("/fooController")
public class MyController {

@Value("${message1}")
public String message1;

@Inject
public ConfigProperties configProperties;

最后,这里是我的课,我注入都归到:

@Service
public class ConfigProperties {

@Value("${message1}")
public String message1;
}

这为我工作,并会为你工作。 祝好运!



Answer 4:

在我来说,我解决了这种方式:在spring-servlet.xml<context:component-scan ... />我把这个:

<context:property-placeholder location="classpath:strings.properties"/>

虽然strings.properties文件我投入src/main/resources/

注: context:property-placeholder标签已经限制的知名度,所以我必须读的地方推荐复制它在每一个方面的文件,在您使用字符串从它。



文章来源: Why is Spring @Value incompatible with @Controller?