当前位置:  开发笔记 > 编程语言 > 正文

Spring在运行时选择bean实现

如何解决《Spring在运行时选择bean实现》经验,为你挑选了3个好方法。

我正在使用带有注释的Spring Beans,我需要在运行时选择不同的实现.

@Service
public class MyService {
   public void test(){...}
}

例如对于我需要的Windows平台MyServiceWin extending MyService,对于我需要的linux平台MyServiceLnx extending MyService.

现在我只知道一个可怕的解决方案:

@Service
public class MyService {

    private MyService impl;

   @PostInit
   public void init(){
        if(windows) impl=new MyServiceWin();
        else impl=new MyServiceLnx();
   }

   public void test(){
        impl.test();
   }
}

请考虑我只使用注释而不是XML配置.



1> nobeh..:

1.实施自定义 Condition

public class LinuxCondition implements Condition {
  @Override
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    return context.getEnvironment().getProperty("os.name").contains("Linux");  }
}

同样的Windows.

2. @ConditionalConfiguration课堂上使用

@Configuration
public class MyConfiguration {
   @Bean
   @Conditional(LinuxCondition.class)
   public MyService getMyLinuxService() {
      return new LinuxService();
   }

   @Bean
   @Conditional(WindowsCondition.class)
   public MyService getMyWindowsService() {
      return new WindowsService();
   }
}

3. @Autowired照常使用

@Service
public class SomeOtherServiceUsingMyService {

    @Autowired    
    private MyService impl;

    // ... 
}



2> grep..:

让我们创建漂亮的配置.

想象一下,我们有Animal界面,我们有DogCat实现.我们想写写:

@Autowired
Animal animal;

但我们应该返回哪个实施?

在此输入图像描述

那么解决方案是什么?有很多方法可以解决问题.我将一起编写如何使用 @Qualifier和Custom Conditions.

首先,让我们创建自定义注释:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
public @interface AnimalType {
    String value() default "";
}

和配置:

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class AnimalFactoryConfig {

    @Bean(name = "AnimalBean")
    @AnimalType("Dog")
    @Conditional(AnimalCondition.class)
    public Animal getDog() {
        return new Dog();
    }

    @Bean(name = "AnimalBean")
    @AnimalType("Cat")
    @Conditional(AnimalCondition.class)
    public Animal getCat() {
        return new Cat();
    }

}

注意我们的bean名称是AnimalBean.为什么我们需要这个豆?因为当我们注入Animal接口时,我们只会编写@Qualifier("AnimalBean")

我们还创建了自定义注释来将值传递给我们的自定义条件.

现在我们的条件看起来像这样(假设"Dog"名称来自配置文件或JVM参数或...)

   public class AnimalCondition implements Condition {

    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        if (annotatedTypeMetadata.isAnnotated(AnimalType.class.getCanonicalName())){
           return annotatedTypeMetadata.getAnnotationAttributes(AnimalType.class.getCanonicalName())
                   .entrySet().stream().anyMatch(f -> f.getValue().equals("Dog"));
        }
        return false;
    }
}

最后注射:

@Qualifier("AnimalBean")
@Autowired
Animal animal;



3> Stanislav..:

您可以将bean注入移动到配置中,如下所示:

@Configuration
public class AppConfig {

    @Bean
    public MyService getMyService() {
        if(windows) return new MyServiceWin();
        else return new MyServiceLnx();
    }
}

另外,您也可以使用配置文件windowslinux,然后与注释您的服务实现@Profile批注,如@Profile("linux")@Profile("windows"),并提供此配置文件用于您的应用程序之一.

推荐阅读
罗文彬2502852027
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有