Spring 将不同的服务实例注入控制器
我有以下控制器和服务Spring 将不同的服务实例注入控制器,spring,model-view-controller,code-injection,autowired,Spring,Model View Controller,Code Injection,Autowired,我有以下控制器和服务 @Controller public class MyController { @Autowired private MyService myService; @RequestMapping(method=RequestMethod.GET, value="/connect.do") public String connect(Model model) { invokeService(); return "xxx"; }
@Controller
public class MyController
{
@Autowired
private MyService myService;
@RequestMapping(method=RequestMethod.GET, value="/connect.do")
public String connect(Model model)
{
invokeService();
return "xxx";
}
private void invokeService()
{
myService.test();
}
}
@Service
public class MyService
{
private int value1 = 200;
private int value2 = 333;
private String value3 ;
private String value4 ;
private String value5 ;
....
public void test()
{
System.out.println(value1++);
foo();
}
private void foo()
{
}
}
当我使用两个浏览器连接到应用程序时,输出是“200”和“201”,这意味着Spring将相同的MyService实例注入控制器以进行不同的连接
当我使用两个不同的连接访问应用程序时,我需要输出为“200”和“200”,因为我需要在“test()”和“foo()”之间共享值1、值2、值3等。春天怎么做?基本上,我希望Spring为不同的连接注入不同的实例。我在ServiceBean中尝试了@Scope(“prototype”),但它不起作用
我可以使用以下方法使其工作:
@Controller
public class MyController
{
private void invokeService()
{
new MyService.test();
}
}
我只是想知道春天怎么做
问这个问题的另一种方式是:如何让多个控制器实例(每个用户连接一个)而不是一个控制器实例为所有连接服务
编辑:通过使用以下代码和2个浏览器连接,我可以看到原型(输出:200)和单例(输出:200 201 202 203)的区别
private void invokeService()
{
myService = applicationContext.getBean( MyService.class );
new MyService.test();
myService = applicationContext.getBean( MyService.class );
new MyService.test();
}
但当我将“applicationContext.getBean(MyService.class)”放在postConstructor中时:
public class MyController implements ApplicationContextAware {
private SearchService searchService;
@PostConstruct
public void init() {
searchService = applicationContext.getBean( SearchService.class );
}
protected ApplicationContext applicationContext;
@Override
public void setApplicationContext( ApplicationContext applicationContext ) throws BeansException {
this.applicationContext = applicationContext;
}
}
在MyService上使用“@Scope(BeanDefinition.Scope_PROTOTYPE)”,当我使用两个浏览器连接到应用程序时,输出仍然是“200”和“201”
不会与@Scope(“PROTOTYPE”)
混合,因为您启用了代理生成(这可能不是您想要的-它很快变得复杂)
将您的MyController
ApplicationContextAware
改为:
public class MyController implements ApplicationContextAware {
public MyService getMyService() {
return applicationContext.getBean( MyService.class );
}
protected ApplicationContext applicationContext;
@Override
public void setApplicationContext( ApplicationContext applicationContext ) throws BeansException {
this.applicationContext = applicationContext;
}
}
现在@Scope(BeanDefinition.Scope\u原型)
将按预期工作
请注意,每次调用getMyService()
时,都会得到一个新的MyService
实例
为什么你的方法(和我以前的方法)不起作用MyController
是一个单例,因此字段myService
只连接了一次-Spring无法在每次访问该字段时为您提供新的bean实例,原因有二:
PS:如果您使用Spring<3.1.2,您将需要指定bean的ID,因为
getBean(类类型)
对于这些版本来说非常慢。非常感谢。我复制了您提供的控制器代码,但没有在服务中使用“@Scope(BeanDefinition.Scope\u PROTOTYPE)”,并且它按照我的预期工作。但是你能解释一下为什么这会给我两个不同的服务实例吗?对不起,这是我的错误操作。我按照你的指示去做,我还是会得到“200”和“201”,该死的:-)和你一样掉进了同样的陷阱。我编辑了我的答案;现在应该可以了。请再试一次。基本上,每次使用MyService获取全新实例之前,我们都需要调用applicationContext.getBean(MyService.class)(它实际上与新的MyService().test()相同)。但是弹簧的设计对我来说没有意义。例如,在我看来,“myService.foo();myService.bar()”应该使用相同的myService实例,如果在一个客户端HTTP请求中调用这两个调用;如果这两个调用由两个客户端HTTP请求调用,那么应该有两个不同的MyService instancesMyController不应该是单例,或者至少Spring应该为用户提供将其设置为非单例的能力。通过使用以下代码private void invokeService()我可以看到原型和单例的区别{myService=applicationContext.getBean(myService.class);new myService.test();myService=applicationContext.getBean(myService.class);new myService.test();}但是当我在postConstructor中使用getBean方法时,当我使用两个浏览器连接到应用程序时,输出仍然是“200”和“201”