如何在运行时为每个http请求选择bean实现

时间:2018-06-11 12:32:30

标签: spring spring-mvc spring-boot

我有两个我的组件实现。

public interface MyComponent {

}

imple1

@Component("impCompf")
@Lazy
@RequestScope
public class ImpComp1 implements MyComponent {

}

imple2

@Component("impComps")
@Lazy
@RequestScope
public class ImpComp2 implements MyComponent {

}

到目前为止,我所做的是创建两个条件:

imple1

public class FirstCondition implements Condition {

        @Override
    public boolean matches(ConditionContext arg0, AnnotatedTypeMetadata arg1) {        

        return staticVariable.contains("impCompf"); 
    }
}

imple2

也是如此

并定义configuration

@Configuration
public class MyConfiguration {
    @Bean
    @Conditional(FirstCondition .class)
    @Primary    
    public MyComponent getComp1() {
       return new ImpComp1();
    }

public static String staticVariable= "impCompf";

并在我的主要controller

@RequestMapping(value="api/{co}", method=RequestMethod.POST)
public ResponseEntity<Modelx> postSe(@PathVariable("co") String co) {
    if(co.contains("impCompf"))
        staticVariable = "impCompf";
    else (co.contains("impComps"))
        staticVariable = "impComps";

我想要的是:对于每个http请求,我想加载正确的实现

但是我得到的是静态变量中首先定义的实现。

如果有另一种优雅和更好的方式,我想了解它。

1 个答案:

答案 0 :(得分:2)

我认为这里有一些关于条件目的的混淆。这些请求在您的请求到达时自动将候选bean自动装入您的控制器。当应用程序开始根据环境和类路径等配置应用程序上下文时,将使用这些...

您不需要创建条件类。这是在上下文启动时定义bean的配置,而不是在运行时基于每个请求定义。

静态变量的使用也存在问题,即具有一个或多个并发请求的场景,或者在多线程可能观察到不同值的情况下,除非使用java内存模型中的某些其他机制(例如{{1或者在关系之前建立一个发生,例如与volatile

有很多方法可以做你想要实现的目标。从最终开始,您似乎正在使用客户端提供的路径参数来确定要调用的服务,您可以使用经典工厂模式以编程方式基于字符串输入返回正确的接口实现。

或者,您可以创建两个不同的控制器方法,这些方法由查询参数或端点名称或路径匹配等区分。然后,您可以通过限定的bean名称注入适当的服务

尽管通常建议使用,但您也可以注入一个应用程序上下文实例并搜索它,按名称或类查找相关的bean:https://brunozambiazi.wordpress.com/2016/01/16/getting-spring-beans-programmatically/ - 虽然这样比较麻烦,但您需要处理类似的事情在某些情况下sychnronized或投射 - 最好避免采用其他方法之一。

相关问题