Spring:new()运算符并自动连接在一起

时间:2014-11-19 18:39:13

标签: spring spring-mvc java-ee

如果我使用Spring,这两种方法中哪一种更正确。 即使我使用了相关性注入,我也可以使用new()运算符吗?可以将两者混合使用吗? 我想对这些概念作一些澄清。 感谢

第一种方法:

@RequestMapping(method=RequestMethod.GET)
public String create(Model model){
 model.addAttribute(new User());
 return "index";
}

第二种方法:

@Autowired
User user;

@RequestMapping(method=RequestMethod.GET)
public String create(Model model){
 model.addAttribute(user);
 return "index";
}

3 个答案:

答案 0 :(得分:3)

通过使用依赖注入并不意味着在整个代码中自动禁止使用new运算符。它只是应用于不同要求的不同方法。

Spring中的Web应用程序由许多由框架实例化的协作bean组成,并且(除非覆盖默认范围)是单例。这意味着它们不能保留任何状态,因为它们在所有请求(线程)之间共享。换句话说,如果您自动装配User对象(或任何其他模型属性),则会在应用程序上下文初始化时创建它,并为任何用户请求提供相同的实例。这也意味着如果请求修改了对象,其他请求也会看到修改。不用说这是多线程应用程序中的错误行为,因为您的User对象(或其他模型属性)属于请求,因此它必须具有非常窄的方法调用范围或最多会话。

您也可以为spring创建具有不同范围的bean,但是对于模型属性初始化的简单方案,new运算符就足够了。如果对bean范围感兴趣,请参阅以下文档:Bean scopes

所以在你的用例中,第二种方法是完全错误的。 但是,您也可以将模型属性的创建委托给spring 如果它们用作命令对象(即,如果要将请求参数绑定到它们)。只需将其添加到方法签名中(使用或不使用modelattribute注释)。

所以你也可以把上面的代码写成

@RequestMapping(method=RequestMethod.GET)
public String create(@ModelAttribute User user){     
 return "index";
}

另见:Supported method argument types

答案 1 :(得分:0)

如果你希望你的bean被Spring“管理”(例如用于依赖注入或PropertySources或任何其他与Spring相关的功能),那么你就不能自己创建新对象。您声明它们(通过XML或JavaConfig)并让Spring创建和管理它们。

如果bean不需要由Spring“管理”,您可以使用new运算符创建一个新实例。

在您的情况下,这个特定的对象 - 用户 - 在代码中的其他地方使用过吗?它被注入任何其他Spring bean吗?或者是否有任何其他Spring bean注入用户?任何其他基于Spring的功能怎么样?

如果所有这些问题的答案都是“否”,那么您可以使用第一种方法(创建一个新对象并将其返回)。 一旦create()方法执行完成,在那里创建的User对象将超出范围并将标记为GC。在此方法中创建的User对象最终将被GC编辑。

答案 2 :(得分:0)

可以在Spring MVC应用程序中以两种方式注入事物。是的,如果做得好,你可以混合注射和创造。

示例中的控制器等组件是由应用程序上下文管理的单例。如果您向他们注入任何东西,那么它是全局的,而不是每个请求或会话!因此用户注入不正确,用户目录也可以。在编写多线程应用程序时请注意这一点!

请求相关的东西可以注入方法,如使用的语言环境,请求,用户主体可以作为参数注入,请参阅Spring MVC Documentation的完整列表。

但是如果你创建了一个模型属性,你可以使用new()从头开始创建它。我不会被春天填满,而是被你的视图用来显示控制器创建的数据。在请求映射方法中创建即可。