为什么 Spring @Value 与 @Controller 不兼容? [英] Why is Spring @Value incompatible with @Controller?

查看:21
本文介绍了为什么 Spring @Value 与 @Controller 不兼容?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找对这个问题的更好理解.解决方法非常简单,即将配置数据移动到另一个没有代理/建议包裹的类,但我认为更好地理解这一点将帮助我避免将来出现其他相关问题,所以我希望任何人都能解释可以提供.

I'm looking for a better understanding of this problem. A workaround is pretty simple, namely move the configuration data to another class that does not have proxies/advice wrapped around it, but I think understanding this better will help me avoid other related problems in the future, so I'd like whatever explanation anyone can provide.

我将 Spring 3.1.0.RELEASE 与 Spring STS 和 vFabric tc 服务器一起使用.使用 @Controller 类实现了一个基本的小型 REST 服务器.这一切都很棒(确实如此),但@Controller 也是@Transactional,在加载时间编织和 vFabric tc 服务器之间,它破坏了 @Value.

I'm using Spring 3.1.0.RELEASE with Spring STS and the vFabric tc server. Implemented a basic little REST server using a @Controller class. That's all great (really, it is), but the @Controller is also @Transactional, and between that and the load time weaving and the vFabric tc server, it breaks @Value.

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

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

    @Transactional
    handleRequest(...) ...


}

还有一个属性文件 app.properties:

And a properties file app.properties:

my.property = SUCCESS

这在 JUnit 下工作正常,测试得到一个 MyAPI 对象,该对象的 prop 设置为SUCCESS".但是当应用程序加载到 vFabric 中时,我猜它会在加载时间编织和代理.无论发生什么,都会创建两个 MyAPI 实例,一个具有 prop == "SUCCESS",另一个(不幸的是处理 http 请求的实例)具有 prop == "${my.prop}".

This works fine under JUnit, with the test getting a MyAPI object that has prop set to "SUCCESS". But when the app gets loaded into vFabric, I'm guessing it gets load time weaving and proxying. Whatever happens, there are two MyAPI instances created, one which has prop == "SUCCESS" and another (which is unfortunately the one that handles the http request) which has prop == "${my.prop}".

总而言之,我称之为魔法的失败,这是我使用 AOP 之类的东西时最大的担忧.即使使用 STS,我也不知道如何追查问题背后的原因或弄清楚这是否是一个严重的错误.如果是 bug,我不知道是 Spring、AspectJ、load-time weaver 还是 vFabric 中的 bug,所以我什至不知道在哪里提交 bug 报告.

So all-in-all I call this a failure of magic, which is my biggest concern with using stuff like AOP. Even with STS I don't know how to track down what is the cause behind the problem or figure out if this is a serious bug. If it is a bug, I don't know whether it's a bug in Spring, AspectJ, the load-time weaver, or vFabric, so I don't even know where to file a bug report.

因此,对于理解这一点的任何帮助将不胜感激.谢谢.

So any help in understanding this would be appreciated. Thanks.

推荐答案

我想通了.这确实是太神奇了.

I figured it out. It was, indeed, too much magic.

我在 STS 中使用 Spring Roo 来生成基本的应用程序框架,然后使用 STS 分解出 Roo,因为我们不想坚持使用它.

I used Spring Roo in STS to generate the basic app framework, then factored out Roo using STS as we didn't want to stick with it.

作为最佳实践",Roo 做的一件事是创建两个 Spring 上下文,一个用于整个应用程序,一个仅限于调度程序 servlet.确切的原因,我仍然没有得到,但我猜他们希望保持表示层的东西,比如控制器,不会蔓延到共享的服务层.axtavt 这里很好地解释了这一点.这一切都被 STS 隐藏了.

One thing Roo does as a "best practice" is create two Spring contexts, one for the whole app, and one limited to the dispatcher servlet. Exactly why, I still haven't gotten to, but I guess they want to keep the presentation layer stuff, such as the Controllers, from creeping into the service layer that is shared. This was nicely explained by axtavt here. This was all hidden from me by STS.

在带有 Roo 的 STS 中,WEB-INF 源不在我预期的位置,在/src/main/resources 下(这是 META-INF 目录所在的位置),而是在/src/main/webapp 下,这是不是 Java 源目录,因此完全单独显示,就在/target 目录的上方,所以我误认为它是输出文件夹.

In STS with Roo, the WEB-INF source is not where I expected it, under /src/main/resources (which is where the META-INF directory is) but instead under /src/main/webapp, which is not a Java source directory and thus shown completely separately, just above the /target directory, so I mistook it for an output folder.

在 applicationContext.xml 中,Roo 插入了过滤器以防止应用程序上下文构建控制器,如 axtavt 的帖子中所述,但它也放入了另一个过滤器以消除扫描 Roo 生成的类.我同时取出了两个过滤器,我并不知道它们在那里做什么,但认为它们只是 Roo 的剩菜.

In the applicationContext.xml, Roo had inserted the filter to prevent the application context from constructing Controllers, as explained in axtavt's post, but it also put in another filter to eliminate scanning Roo generated classes. I took both filters out at the same time, not really knowing what they were there for but thinking they were just Roo leftovers.

所以现在我遇到了 控制器被创建两次的问题如前所述.应用程序上下文中的一个获取分配的属性,因为它正在使用 applicationContext.xml 并查找属性文件.但为什么他们都没有得到属性集?

So now I've got the problem of the Controllers being created twice as explained before. And the one in the application context gets the property assigned, because it is using the applicationContext.xml and finding the properties file. But why weren't they both getting the properties set?

这让我回到了模糊的 webapps 文件夹.Roo 在 WEB-INF 文件夹中放置了 web.xml(自然)和一个包含 webmvc-config.xml 文件的 spring 文件夹.此配置文件设置为仅扫描、创建和设置控制器.web.xml 文件将 web 应用程序设置为使用 applicationContext.xml,将 dispatcherServlet 设置为使用 webmvc-config.xml,所以我应该将过滤器留在 applicationContext.xml 中以避免双重创建.

Which gets me back to the obscured webapps folder. Inside the WEB-INF folder Roo had placed the web.xml (naturally) and a spring folder containing a webmvc-config.xml file. This config file was set up to scan, create, and set up just the Controllers. The web.xml file sets up the web app to use the applicationContext.xml and the dispatcherServlet to use the webmvc-config.xml, so I should have left the filter in the applicationContext.xml to avoid the double creation.

最后一块拼图是这个 webmvc-config.xml 文件.由于这是设置控制器的上下文, 文件需要具有 <context:property-placeholder/>配置好,以便它可以找到属性文件.

The final piece of the puzzle was this webmvc-config.xml file. Since that is the context in which the Controllers get set up, that file needed to have the <context:property-placeholder/> configured as well so that it could find the properties file.

这篇关于为什么 Spring @Value 与 @Controller 不兼容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆