Spring根据当前范围注入不同的bean

时间:2016-03-07 16:28:54

标签: java spring spring-mvc dependency-injection

我有两个定义了相同类的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 Application上下文是否可以自动注入正确的bean? 我希望在Web上下文中获取myBeanRequest bean时注入MyPrototype(例如在控制器中),并且我希望在没有Web上下文时注入myBeanSingleton (例如,当我通过Quartz调度程序运行一些代码时)。

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

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

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

2 个答案:

答案 0 :(得分:0)

我会做的解决方法:

创建一个扩展公共接口“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;
        }
    }

答案 1 :(得分:0)

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

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

所以我的建议是小心地将你的bean分类到正确的层中,然后将当前属于两个bean的那些分成2个不同的bean。这可能是一项很大的工作,但是如果你继续进行一种奇怪的设计,那么随着时间的推移它会变得更糟......

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