代码之家  ›  专栏  ›  技术社区  ›  GolamMazid Sajib

动态选择依赖项而不使用if else

  •  0
  • GolamMazid Sajib  · 技术社区  · 6 年前

    如果没有if-else条件,我如何选择依赖关系。

    假设我有一个接口:

    public interface A{
    
    String doSomething(String req);
    }
    

    有两个服务工具 A :

    @Component
    public class FirstImpl implements A{
    
       @override
       String doSomething(String req){
       return "something";
      }
    }
    

    以及:

    @Component
    public class SecondImpl implements A{
    
     @override
        String doSomething(String req){
        return "something";
      }
    }
    

    现在我创建一个AdapterService类:

    @Component
    public class AdapterService{
        @Autowired
        private FirstImpl first;
        @Autowired
        private SecondImpl second;
    
        public getService(String name){
            if("name".equals("First")){
                return first;
            }else if("name".equals("Second")){
                return second;
            }
        }
    }
    

    现在调用实现:

    @Service
    public class BusinessService{
        @Autowired
        private AdapterService adapterService;
    
        void doSomething(String name,String req){
            return adapterService.getService(name).doSomething();
        }
    }
    

    现在,如果需要创建另一个类,该类在ServiceAdapter类中实现then need to add条件。就像 "Third".equals(name) 返回另一个注入的服务。对于每个新服务,都需要添加另一个if-else条件并注入相应的服务。我怎样才能避免这个适配器类。Spring从name中动态选择dependency。

    2 回复  |  直到 5 年前
        1
  •  2
  •   GolamMazid Sajib    6 年前

    如果你有权 applicationContext 对象,可以调用

    applicationContext.getBean(名称)

    完全避免使用ServiceAdapter类。你只需要把那些豆子放在容器里。

    试试这个:

    @Component
    public class AdapterService{
        @Autowired
        private ApplicationContext applicationContext;
    
        public A getService(String name){
            return applicationContext.getBean(name,A.class);
        }
    }
    
        2
  •  1
  •   Joop Eggen    6 年前

    这里是 java SPI, Service Provider Interface ,请参见 here 也可以,就像试着用弹簧锤一样。

    对于接口 x.y.z.A 有一种使用java SPI实现类的发现机制。

    你可以有几个罐子。

    他们有一个文本文件 META-INF/services/x.y.z.A 在不以开头的行上实现类 # .

    由于您可能不希望在按名称选择类的对象之前将其实例化,因此您可以对该类使用运行时批注,或者在 一个工厂,有少量的建设开销,创造了一个A。

    ServiceLoader<Dictionary> loader = ServiceLoader.load(A.class);
    Iterator<A> dictionaries = loader.iterator();