Kim*_*Kim 25 java spring spring-mvc spring-web
TestController.java
@RestController
public class TestController {
@Autowired
private TestClass testClass;
@RequestMapping(value = "/test", method = RequestMethod.GET)
public void testThread(HttpServletResponse response) throws Exception {
testClass.doSomething();
}
}
Run Code Online (Sandbox Code Playgroud)
TestClass.java
@Component
@Scope("prototype")
public class TestClass {
public TestClass() {
System.out.println("new test class constructed.");
}
public void doSomething() {
}
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,我正在试图弄清楚TestClass当访问"xxx/test"时是否注入了新的."new test class constructed."只打印一次(第一次我触发"xxx/test"),而我期待它打印平等.那个卑鄙的@Autowired对象只能是@Singleton吗?@Scope工作怎么样?
编辑:
TestController.java
@RestController
public class TestController {
@Autowired
private TestClass testClass;
@RequestMapping(value = "/test", method = RequestMethod.GET)
public void testThread(HttpServletResponse response) throws Exception {
testClass.setProperty("hello");
System.out.println(testClass.getProperty());
}
}
Run Code Online (Sandbox Code Playgroud)
我试过@Valerio Vaudi解决方案,注册为Scope(scopeName = "request").这是我访问"xxx/test"时的三次结果
(第一次)
(第二)
(第三)
我不明白为什么结果为null,因为每次使用它都不会重建一个新结果.
然后我试着@Nikolay Rusev解决方案@Scope("prototype"):
(第一)
(第二)
(第三)
这很容易理解,因为每次使用它(TestClass)时,Spring都会自动重新生成它的新实例.但是第一个场景我仍然无法理解,因为它似乎只为每个请求保留了一个新实例.
真正的目的是:在每个请求生命周期中,testClass需要一个新的(如果需要),并且只需要一个.此时似乎只有ApplicationContext解决方案是可行的(我已经知道),但我只是想知道这是否可以通过使用@Component+ @Scope+ 自动完成@Autowired.
Nik*_*sev 23
以上所有答案都是正确的.默认情况下singleton,控制器是,并且注入testClass实例化一次,因为默认范围代理模式DEFAULT来自spring doc.
public abstract ScopedProxyMode proxyMode指定是否应将组件配置为作用域代理,如果是,则指定代理是基于接口还是基于子类.默认为ScopedProxyMode.DEFAULT,它通常表示除非在组件扫描指令级别配置了不同的默认值,否则不应创建范围代理.
类似于Spring XML中的支持.
另请参见:ScopedProxyMode默认值:org.springframework.context.annotation.ScopedProxyMode.DEFAULT
如果你想在每次需要时注入新实例,你应该TestClass改为:
@Component
@Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class TestClass {
public TestClass() {
System.out.println("new test class constructed.");
}
public void doSomething() {
}
}
Run Code Online (Sandbox Code Playgroud)
使用这个额外的配置,注入的testClass不是TestClassbean,而是bean的代理TestClass,这个代理将理解prototype范围,并且每次都需要返回新的实例.
如前所述,控制器默认为单例,这就是为什么实例化和注入TestClass仅在其创建时执行一次。
解决方案可以是注入应用程序上下文并手动获取Bean:
@RestController
public class TestController {
@Autowired
ApplicationContext ctx;
@RequestMapping(value = "/test", method = RequestMethod.GET)
public void testThread(HttpServletResponse response) throws Exception {
((TestClass) ctx.getBean(TestClass.class)).doSomething();
}
}
Run Code Online (Sandbox Code Playgroud)
现在,当TestClass请求一个bean 时,Spring知道它是@Prototype,将创建一个新实例并返回它。
另一个解决方案是制造控制器@Scope("prototype")。
默认情况下,Spring 控制器是单例(由于其无状态性质,这是可以的),其他 Spring bean 也是如此。
TestClass这就是为什么只为唯一 实例实例化一个实例就足够了TestController。
TestClass再次实例化很容易- 只需将其注入另一个控制器或以编程方式从上下文中获取
| 归档时间: |
|
| 查看次数: |
14672 次 |
| 最近记录: |