Spring启动时的策略

rin*_*ing 7 java spring design-patterns dependency-injection spring-boot

嗨,我在Spring启动应用程序中有一个策略模式.我所有的策略都有自动装配的构造函数.我是春季靴子的新手.我没有最简单的想法如何为策略类编写工厂,因为自动装配的构造函数已注入依赖项.我感谢任何帮助.

注意:我遗漏了Intefaces和基类,以免混淆样本.

public class StrategyA implement Strategy {
private DependencyA depA;
private DependencyB depB;
   @Autowired
   public StragegyA(DependencyA depA, DependencyB depB) {
       this.depA = depA;
       this.depB = depB;
   }
}

public class StrategyB implements Strategy {
private DependencyA depA;
private DependencyB depB;
   @Autowired
   public StragegyB(DependencyA depA, DependencyB depB) {
       this.depA = depA;
       this.depB = depB;
   }
}

public class StrategyFactory {
    public Strategy getStrategy(String strategyName) {
      if (name.equals("StrategyA")) {
         <b>return StrategyA; //My problem is here
      } else {
         return StrategyB; // And Here
      }
    }
}
Run Code Online (Sandbox Code Playgroud)

JB *_*zet 9

使您的StrategyFactory成为另一个Spring bean,并在工厂中注入所有策略:

@Component
public class StrategyFactory {
    private final List<Strategy> strategies;

    @Autowired
    public StrategyFactory(List<Strategy> strategies) {
        this.strategies = strategies;
    }

    public Strategy getStrategy(String strategyName) {
        // iterate through the strategies to find the right one, and return it.
    }
}
Run Code Online (Sandbox Code Playgroud)

我通常使用枚举而不是字符串来识别策略,并且我使每个策略返回它处理的枚举值,因此迭代可以像

return strategies.stream().filter(strategy -> strategy.getType() == type).findAny().orElseThrow(
    () -> new IllegalStateException("No strategy found for type " + type));
Run Code Online (Sandbox Code Playgroud)

当然,您也可以将策略存储在构造函数内的Map中,以进行查找O(1).


JEY*_*JEY 5

以前的所有答案都使用了非常直接的 spring DI 用法。但是,也可以使用 ServiceLocatorFactoryBean 来创建工厂,而无需在工厂中指定任何 bean。首先为你的工厂定义一个接口:

public interface MyFactory {
    Strategy get(String type);
}

// Could be an abstract class
public interface Strategy {
    void doStuff();
}
Run Code Online (Sandbox Code Playgroud)

然后在您的应用程序中:

@Configuration
public class AppConfiguration {
    @Autowired
    private BeanFactory beanFactory;

    public ServiceLocatorFactoryBean myFactoryLocator() {
        final ServiceLocatorFactoryBean locator = new ServiceLocatorFactoryBean();
        locator.setServiceLocatorInterface(MyFactory.class);
        locator.setBeanFactory(beanFactory);
        return locator;
    }

    @Bean
    public MyFactory myFactory() {
        final ServiceLocatorFactoryBean locator = myFactoryLocator();
        locator.afterPropertiesSet();
        return (MyFactory) locator.getObject();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以定义实现/扩展的 bean(使用注解 @Service、@Component 或 @Bean),它们会自动注册到 MyFactory bean 中,并且可以通过以下方式创建:

myFactory.get("beanName");
Run Code Online (Sandbox Code Playgroud)

最好的部分是您可以将 Strategy bean 注册为惰性且具有不同范围。