@autowired字段以及@autowired构造函数

时间:2013-07-23 13:51:24

标签: spring spring-mvc dependency-injection autowired

我有一个spring MVC应用程序。我有一个连接为单例的bean,也是一个自动连接但是请求范围的字段。 例如:

class Hello {

  @Autowired
  BDepend b; // this is defined as a request scope bean

  @Autowired
  public Hello(ADepend a){
  }
}

这里我的类Hello是单例,但BDepend是请求范围对象。 Spring是如何为每个请求处理Bdepend的正确实例,因为Hello是一个单例。

1 个答案:

答案 0 :(得分:1)

默认情况下,应用程序sturtup会出现运行时异常。像这样:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'b': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton;

要在某些单例中使用请求范围对象,您需要每次从应用程序上下文获取一个新的实例。你可以这样做:

  • 直接使用应用程序上下文

    class Hello {
    
      @Autowired
      private ApplicationContext ctx;
    
      @Autowired
      public Hello(ADepend a){
      }
    
      public useB(){
         BDepend instance = ctx.getBean(BDepend.class);
         instance.doSomething();
      }
    }
    
  • 或通过javax.inject.Provider获取新的实例。

    class Hello {
    
      @Autowired
      private Provider<BDepend> provider;        
    
      @Autowired
      public Hello(ADepend a){
      }
    
      public useB(){
         BDepend instance = this.provider.get();
         instance.doSomething();
      }
    }
    
  • 或为此bean声明范围代理:

    @Component
    @Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
    class BDepend {
    
    }
    
    class Hello {
    
      @Autowired
      private BDepend b;        
    
      @Autowired
      public Hello(ADepend a){
      }
    
      public useB(){
         b.doSomething();
      }
    }
    
  • 或使用系统范围的范围代理

    <context:component-scan base-package="com.mycompany.beans" scoped-proxy="targetClass" />
    

我个人更喜欢第二个选项(javax.inject.Provider):从代码中可以清楚地看出你的bean有不同的范围。