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

标签 spring spring-mvc spring-boot

我的组件有两个实现。

public interface MyComponent {

}

实现1

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

}

imple2

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

}

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

实现1

public class FirstCondition implements Condition {

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

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

对于imple2也是如此

并定义一个配置

@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 请求,我想加载正确的实现

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

如果还有其他优雅且更好的方法,我想知道。

最佳答案

我认为这里对于条件的目的存在一些混淆。当您的请求到达以将候选 bean 自动连接到 Controller 时,这些并没有被使用。当应用程序启动时,将使用这些来根据环境和类路径等配置应用程序上下文...

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

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

有多种方法可以实现您想要实现的目标。由于最终,您似乎使用客户端提供的路径参数来确定要调用哪个服务,因此您可以使用经典工厂模式以编程方式基于字符串输入返回正确的接口(interface)实现。

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

尽管通常建议这样做,但您也可以注入(inject)应用程序上下文实例并搜索它以按名称或类查找相关 bean:https://brunozambiazi.wordpress.com/2016/01/16/getting-spring-beans-programmatically/ - 虽然这更麻烦,并且您需要处理诸如 org.springframework.beans.factory.NoSuchBeanDefinitionException 之类的事情或在某些情况下进行转换 - 最好避免使用其他方法之一。

关于spring - 如何在运行时为每个 http 请求选择 bean 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50797834/

相关文章:

java - 使用 Spring Boot 进行 session 管理?

java - Spring 中的日志消息银行

java - 如何在现有 Spring Hibernate 应用程序中包含 Spring JPA

java - 如何在spring webflow中实现Switch/if else if语句?

spring - 不使用 spring batch + spring boot + sql server 应用程序运行 DDL 脚本

java - 在heroku上部署spring boot时Google api重定向问题

java - 带有配置文件的 Spring Boot Maven 多模块项目 - 未找到其他模块的包

java - Spring中如何实现基于客户端 token 的限速?

java - 传递多个值。获取 org.hibernate.exception.SQLGrammarException : could not extract ResultSet] with root cause

Spring安全+ session : Receive "Set-Cookie" header but not set in browser