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

Spring:new()运算符并自动连接在一起,spring,spring-mvc,jakarta-ee,Spring,Spring Mvc,Jakarta Ee,如果我使用Spring,这两种方法中哪一种更正确。 即使使用dipendency injection,我也可以使用new()操作符吗?我可以混合使用这两种操作符吗? 我想澄清一下这些概念。 谢谢 第一种方法: @RequestMapping(method=RequestMethod.GET) public String create(Model model){ model.addAttribute(new User()); return "index"; } 第二种方法: @Autowir

如果我使用Spring,这两种方法中哪一种更正确。 即使使用dipendency injection,我也可以使用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";
}

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

如果bean不需要由Spring“管理”,那么可以使用new操作符创建一个新实例

在您的例子中,这个特定的对象-用户-是否在代码中的其他地方使用?它是否被注射到其他春豆中?或者是否有其他Springbean被注入到用户中?其他基于Spring的功能如何


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

在Spring MVC应用程序中,可以通过两种方式注入东西。是的,如果做得好的话,你可以把注射和创作结合起来

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

与请求相关的东西可以被注入到方法中,比如所使用的语言环境、请求、用户主体可以被注入为参数,请参阅


但是,如果创建模型属性,可以使用new()从头开始创建它。spring将不填充我,而是供您的视图用于显示控制器创建的数据。在请求映射方法中创建时,这是正常的。

使用依赖项注入并不意味着在整个代码中自动禁止使用
new
运算符。只是针对不同的需求采用了不同的方法

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

您也可以让SpringCreateBean具有不同的作用域,但是对于一个简单的模型属性初始化场景,
new
操作符就足够了。如果对bean作用域感兴趣,请参阅以下文档:

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

因此,您也可以编写上面的代码

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

另请参见:

您的最后一句话不正确。这不是“超出范围”。该对象仍在由
模型
引用的
模型
对象中引用。它最终将被传输到
HttpServletRequest
属性。仅当请求处理周期完成且容器回收(或丢弃)时
ServletRequest
ServletResponse
User
对象作为GC的候选对象。您可能希望讨论使用第二种方法和原型范围bean。我考虑过这一点,但这只会使答案更复杂,因此我将其排除在外。如果您有更好的解释方法,请随时回答此问题。我只能在方法外部使用@autowire注释,因为如果我将其插入方法内部,则会出现一些错误。如果用户对象仅在“create”方法内部使用,我如何解决它?在这种情况下,我认为您不需要@autowire用户对象。在Create()方法中创建并填充对象,就完成了。如果你想在github上发布你的源代码,我可以看一下。