【问题标题】:Spring inject different bean depending on current scopeSpring根据当前范围注入不同的bean
【发布时间】:2016-06-21 07:23:48
【问题描述】:

我定义了两个相同类的 bean:

@Bean
@Scope("singleton")
public MyBean myBeanSingleton(){
    return new MyBean()
}

@Bean
@Scope("request")
public MyBean myBeanRequest(){
    return new MyBean()
}

还有另一个原型作用域 bean:

@Component
@Scope("prototype") 
public class MyPrototype {
    @Autowired
    private MyBean myBean
}

当没有可用的请求时,Spring 应用程序上下文是否可以自动注入正确的 bean? 我希望myBeanRequest 在 Web 上下文中(例如在控制器中)获取 MyPrototype bean 时被注入,我希望在没有 Web 上下文时注入 myBeanSingleton(例如当我运行时)通过 Quartz 调度程序的一些代码)。

目前spring每次都尝试注入myBeanRequest,因此在没有可用请求时失败。

我非常想坚持使用MyPrototype 的 ONE bean 定义,因为会有许多不同的 bean 需要类似的行为,因此使用限定符和两个不同的 bean 定义(用于请求和单例)不适合我的案例。

也许有一些 spring 组件可以让我以编程方式选择要注入的 bean?

【问题讨论】:

  • 你试过弹簧型材吗?
  • 嗨,弹簧配置文件不允许我同时使用这两种方案。如果我想要请求 bean 或单例 bean,我将不得不选择。我希望spring根据是否有可用的网络请求自动注入正确的bean......

标签: java spring spring-mvc dependency-injection


【解决方案1】:

Spring 用途广泛,但目前,您有两个相同类的 bean,没有任何限定符,因此 Spring 无法区分它们。即使在最低级别手动使用ApplicationContext.getBean(),也只能传递一个类和一个名称。

我很抱歉这么说,但我担心你在这里遇到了一个主要的建筑设计问题。 Spring方式将尊重分层架构。这意味着一个 bean 应该只位于一个 layer 任一 web 层(控制器、拦截器、过滤器)中——并且在没有可用请求的情况下使用它应该没有意义,因为它的使用应该只是为了帮助在处理一个,或在非 Web 层(例如服务或持久性)中,它应该在不知道 http 意味着什么的情况下工作。并且规则是 web 可以调用 non web,但绝不会发生相反的情况。

所以我的建议是在正确的层中仔细分类你的 bean,并将当前属于双方的那些分成 2 个不同的 bean。这可能是大量的工作,但如果你继续进行一个奇怪的设计,随着时间的推移它可能会变得更糟......

我知道这不是预期的答案,但这是我能给你的最好的答案。

【讨论】:

  • 我怀疑完全相同的事情,我倾向于接受它作为答案。我知道从服务 Web 的角度来看,这种分离是正确的方法,但是如果我要将我的场景扩展到其他自定义(由我定义)范围,它似乎是 spring 框架的限制。也许有一种方法可以以编程方式返回我选择的任何 bean?在我可以实现的每次 @Autowire 尝试上运行的某种方法检查什么是最具体的可用范围并返回正确的 bean?
【解决方案2】:

我会做的解决方法:

创建扩展通用接口“MyBean”的 RequestMyBean 和 SessionMyBean。

然后

     @Component
     @Scope("prototype") 
     public class MyPrototype {
        @Autowired(required=false)
        private RequestMyBean myReqBean

        @Autowired(required=false)
        private SessionMyBean mySessBean

        public MyBean getMyBean(){
             if(myReqBean != null){
                 return myReqBean;
             }
             return mySessBean;
        }
    }

【讨论】:

  • 实际上它在我的场景中不起作用。正如我所说,我将有多个(超过 100 个 bean)具有类似行为,因此我需要每个程序员为每个程序员重写代码。此外,在生产中,MyBean 实际上有 4 个不同的 bean(单例、来自子上下文的单例、会话和请求)——因此代码会比这更复杂。而且我不排除添加其他自定义范围“MyBeans”的可能性
  • 我明白了。也许您可以查看 Spring 类,该类在不存在时无法自动装配请求 bean 时会引发异常。然后尝试重载它,以便它尝试查看会话范围。当您迁移到新的 Spring 版本时,这是一个很难维护的解决方案......
猜你喜欢
  • 2020-03-18
  • 1970-01-01
  • 1970-01-01
  • 2020-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-10
  • 1970-01-01
相关资源
最近更新 更多