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实例,原因有二:

  • 这意味着Spring必须分析类的字节码,以找到代码访问字段的所有位置
  • 它会以其他方式破裂。例如,当您调用bean的两个方法时:

    myService.foo(); myService.bar();//你真的想要一个新的豆子吗


  • 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”