Configure Implementation Class of Abstract Factory with Spring

后端 未结 3 1709
遥遥无期
遥遥无期 2020-12-30 17:13

For my application, I have a Scale interface and multiple classes implementing this interface, for example NormalizedScale, LogScale,

相关标签:
3条回答
  • 2020-12-30 17:51

    As for spring 5.x there's a simpler and cleaner way of doing this. I have decided to use @ConditionalOnProperty annotation but you may choose any @Conditional* of your preference.

    Here's the thing, I've have simplified to extreme:

    public interface MyService {}
    
    @Service
    @ConditionalOnProperty(prefix = "myService", name = "Impl", havingValue = "Some")
    public class SomeService implements MyService {}
    
    @Service
    @ConditionalOnProperty(prefix = "myService", name = "Impl", havingValue = "Foo")
    public class FooService implements MyService {}
    
    @Service
    public class SimpleService {
    
      @Autowired
      SimpleService(MyService service) {
        // service instance will depend on configuration
      }
    }
    

    I'm using springboot so I've decided to use application.properties in order to set values via environment variables like this:

    myService.Impl=${MY_SERVICE_IMPL}
    

    Then, I have a fully dynamic injection based on environment variables that may be passed to a docker container for instance.

    0 讨论(0)
  • 2020-12-30 17:53

    You can simply use "Qualifiers" which is basically going to point to a specific "named" bean. By default the bean names are the name of your classes, with the first letter in lower case (MyClass -> myClass). If you want to define your own names you can do as follow :

    @Service("customizedBeanName")
    

    You would end up doing something like this :

    @Autowired
    @Qualifier("logScale")
    private Scale logScale;
    
    @Autowired
    @Qualifier("anotherScale")
    private Scale anotherScale;
    
    0 讨论(0)
  • 2020-12-30 17:55

    There are a couple of different Spring-like ways you can handle this. The approach I have personally gone for looks a bit like this:

    public interface ScaleFactory {
    
        public Scale newInstance();
        public String type();
    
    }
    
    public class FirstScaleFactory implements ScaleFactory {
    
        public Scale newInstance() {
            return new FirstScale();
        }
    
        public String type() {
            return "first";
        }    
    
    }
    
    public class SecondScaleFactory implements ScaleFactory {
    
        public Scale newInstance() {
            return new SecondScale();
        }
    
        public String type() {
            return "second";
        }    
    
    }
    
    public class ScaleManager {
    
        private final Map<String, ScaleFactory> factories;
    
        @Autowired
        public ScaleManager(List<ScaleFactory> factories) {
            this.factories = factories.stream()
                .collect(Collectors.toMap(f -> f.type(), Function::identity));
        }
    
        public Scale newInstance(String type) {
            return Optional.ofNullable(factories.get(type))
                .map(factory -> factory.newInstance())
                .orElseThrow(IllegalArgumentException::new);
        }
    
    }
    

    With this approach, your ScaleManager is a standard Spring bean that can be wired into any class that needs a scale instance. At initialization time, it gets all ScaleFactories that are defined in the Spring context, and autowires them in as a List<ScaleFactory>, which is then converted to a Map (where the ScaleFactory type is the key). This avoids you needing to worry about class names of Scale, and gives your the ability to change them later (as long as you keep the type key consistent)`

    Your ScaleFactory implementations can then do whatever they need to do. For example, if you have one type of Scale that you know is immutable, you can have the factory return the same instance every time. Alternatively you can have every invocation return a separate instance - the instantiation of the Scale is up to the implementation-dependent factory.

    0 讨论(0)
提交回复
热议问题