4

Hallo Ich habe ein Strategie-Muster in einer Spring-Boot-Anwendung. Alle meine Strategien haben Autowired Konstruktoren. Ich bin neu im Springboot. Ich habe keine einfache Idee, wie ich meine Fabrik für Strategieklassen schreiben werde, da Autowired-Konstruktoren Abhängigkeiten injiziert haben. Ich schätze jede Hilfe, die ich dabei bekomme.Strategie innerhalb Spring Boot

HINWEIS: Ich lasse aus Schnittstellen und Basisklassen aus, um Probe nicht zu durcheinander zu bringen.

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 
     } 
    } 
} 

Antwort

3

Alle bisherigen Antworten sind eine ziemlich geradlinig Verwendung von Feder DI verwenden. Es ist jedoch auch möglich, ServiceLocatorFactoryBean zu verwenden, um eine Factory zu erstellen, ohne eine Bean in der Factory angeben zu müssen. zunächst eine Schnittstelle für Ihre Fabrik definieren:

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

// Could be an abstract class 
public interface Strategy { 
    void doStuff(); 
} 

Dann in Ihrer Anwendung:

@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(); 
    } 
} 

Jetzt können Sie Bohne (mit Kommentierung @Service, @Component oder @Bean) definieren, die implementiert/erstreckt und sie werden automatisch in die myFactory Bean registriert und können erstellt werden:

myFactory.get("beanName"); 

der beste Teil Sie die Strategie-Bean kann registrieren als faul und Witz h verschiedene Bereiche.

5

Machen Sie Ihre StrategyFactory andere Spring-Bean und injizieren alle Strategien in der Fabrik:

@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. 
    } 
} 

ich in der Regel eine ENUM verwenden, anstatt einen String den stratehy zu identifizieren, und ich mache jede Strategie Rückkehr der eNUM-Wert, dass es behandelt, so kann die Iteration so einfach sein wie

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

natürlich können Sie auch die Strategien in einer Karte innerhalb des Konstruktors speichern können, das Nachschlag-O zu machen (1) .

2
@Component 
public class StrategyFactory { 
    private StrategyA sA; 
    private StrategyB sB; 
    @Autowired 
    public StrategyFactory (StrategyA sA, StrategyB sB) { 
     this.sA = sA; 
     this.sB = sB; 
    } 
    public Strategy getStrategy(String strategyName) { 
     if (name.equals("StrategyA")) { 
     return sA; //My problem is here 
     } else { 
     return sB; // And Here 
     } 
    } 
} 

den gleichen Ansatz verwenden mit autowiring alle Strategien

3

Ich schlage vor, würden Sie Ihren StrategyFactory eine Bohne zu machen und es in ein Map<String, Strategy> injizieren. Spring füllt es mit dem Namen der Strategie-Bean als Schlüssel und ein Wert wird selbst eine Strategie sein. Dann müssen Sie nur get auf diesem Map anrufen. Hier

ein Beispiel:

@SpringBootApplication 
public class So44761709Application { 

    public static void main(String[] args) { 
     SpringApplication.run(So44761709Application.class, args); 
    } 

    public interface Strategy { } 

    @Component 
    public static class DependencyA {} 
    @Component 
    public static class DependencyB {} 

    @Component("StrategyA") 
    public static class StrategyA implements Strategy { 
     private DependencyA depA; 
     private DependencyB depB; 
     @Autowired 
     public StrategyA(DependencyA depA, DependencyB depB) { 
      this.depA = depA; 
      this.depB = depB; 
     } 
    } 

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

    @Component 
    public class StrategyFactory { 
     @Autowired 
     private Map<String, Strategy> strategies; 

     public Strategy getStrategy(String strategyName) { 
      return strategies.get(strategyName); 
     } 
    } 

    @Bean 
    CommandLineRunner run(StrategyFactory strategyFactory) { 
     return args -> { 
      System.out.println(strategyFactory.getStrategy("StrategyB").getClass().getSimpleName()); 
      System.out.println(strategyFactory.getStrategy("StrategyA").getClass().getSimpleName()); 
     }; 
    } 
} 

Drucke:

StrategyB 
StrategyA