Java Spring根据当前范围注入不同的bean
我定义了同一类的两个bean:Java Spring根据当前范围注入不同的bean,java,spring,spring-mvc,dependency-injection,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 MyPro
@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?
我希望在web上下文中获取MyPrototype
bean时(例如在控制器中)注入myBeanRequest
,并且我希望在没有web上下文时(例如,当我通过Quartz调度程序运行一些代码时)注入myBeanSingleton
目前spring每次都尝试注入myBeanRequest
,因此在没有可用请求时失败
我非常希望坚持使用MyPrototype
的一个bean定义,因为将有许多不同的bean需要类似的行为,因此使用限定符和两个不同的bean定义(用于请求和单例)不适合我的情况
也许有一些spring组件可以让我通过编程选择注入哪个bean?我要做的工作是: 创建扩展公共接口“MyBean”的RequestMyBean和SessionMyBean 然后
Spring的用途非常广泛,但目前,您有两个同一类的bean,没有任何限定符,因此Spring无法区分它们。即使在手动使用
ApplicationContext.getBean()
的最低级别,也只能传递类和名称
我很抱歉这么说,但我恐怕你们这里有一个重大的建筑设计问题。Spring的方式是尊重分层架构。这意味着一个bean应该只存在于一个层,或者web层(控制器、拦截器、过滤器),在没有可用请求的情况下使用它是没有意义的,因为它的使用应该只用于帮助处理一个层,或者在非web层(比如服务或持久性)中,并且它应该在不知道http意味着什么的情况下工作。规则是web可以调用非web,但不应该出现相反的情况
所以我的建议是小心地将您的bean分类到正确的层中,并将当前属于这两个层的bean拆分为两个不同的bean。这可能是一个很大的工作,但如果你继续一个奇怪的设计,它可能会变得更糟,随着时间的推移
我知道这不是预期的答案,但这是我能给你的最好答案。你试过spring配置文件吗?嗨,spring配置文件不允许我同时使用这两种方案。我必须选择是要请求bean还是单例bean。我想让spring自动注入正确的bean,这取决于是否有可用的web请求……实际上,它在我的场景中不起作用。正如我所说的,我将有多个(超过100个)具有类似行为的bean,因此我将要求每个程序员为每个bean重写代码。此外,在生产环境中,MyBean实际上有4个不同的bean(singleton、来自子上下文的singleton、session和request),因此代码甚至比这更复杂。我不排除添加其他自定义范围的“MyBeans”的可能性。也许您可以看看Spring类,它在不存在时无法自动连接请求bean时抛出异常。然后尝试重载它,以便它尝试查看会话范围。当您迁移到新的spring版本时,这是一个很难维护的解决方案,但是…我怀疑完全相同的事情,我倾向于接受它作为答案。我理解从服务web的角度来看,这种分离是正确的方法,但是如果我要将我的场景扩展到其他自定义(由我定义)范围,这似乎是spring框架的一个限制。也许有一种方法可以通过编程返回我选择的bean?在我可以实现的每个
@Autowire
尝试上运行的某种方法,它检查可用的最特定范围并返回正确的bean?
@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;
}
}