Spring ServiceLocator还是纯工厂模式?

Kak*_*ait 12 java spring dependency-injection service-locator

99%的我的依赖是通过@Autowired Spring注释用DI模式管理的.

然而,在特定情况下,我无法确定在运行时使用哪个实现.

最着名的情况是解析器的多重实现.

第一个解决方案是使用多个@Autowired(丑陋模式)

Interface Parser {
    <T> T parse();
}

@Component("JsonParser")
class JsonParser implements Parser {
    ...
}

@Component("XmlParser")
class XmlParser implements Parser {
    ...
}

class MyService {
    @Autowired
    @Qualifier("XmlParser")
    Parser xmlParser;

    @Autowired
    @Qualifier("JsonParser")
    Parser jsonParser;

    ...     
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我有大量的实现,那是不可接受的.

第二个解决方案是使用Spring的ServiceLocator

interface ParserServiceLocatorFactory {
    public Parser getParser(String parserName);
}

interface Parser {
    <T> T parse();
}

@Component("JsonParser")
class JsonParser implements Parser {
    ...
}

@Component("XmlParser")
class XmlParser implements Parser {
    ...
}

class MyService {
    @Autowired 
    ServiceFactory parserServiceLocatorFactory;

    void exampleMethod() {
        Parser xmlParser = parserServiceLocatorFactory.getParser("XmlParser");
    }
}
Run Code Online (Sandbox Code Playgroud)

这种方式对我来说似乎是正确的,但与第三种解决方案相比较?

第三种解决方案是使用纯工厂模式并注入它.

@Component
public ParserFactory {
    Parser getParser(String parserName) {
        ...
    }
}

interface Parser {
    <T> T parse();
}

@Component("JsonParser")
class JsonParser implements Parser {
    ...
}

@Component("XmlParser")
class XmlParser implements Parser {
    ...
}

class MyService {
    @Autowired 
    ParserFactory parserFactory

    void exampleMethod() {
        Parser xmlParser = parserFactory.getParser("XmlParser");
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你有以前解决方案的pro/con,或者甚至更好地解决我的问题?

PS:这是伪代码我可能会错过一些小东西:)

Mak*_*das 10

作为选项,您可以使用列表注入:

public class SomeService {

    @Autowired 
    private List<Parser> parsers;

    public doSomethingWithParser(...) {
        ...
        Parser parser = getParser(JsonParser.class);
        parser.parse(...);
        ...
    }

    private Parser getParser(Class<Parser> targetClass) {
        Parser result = null;
        for(Parser parser : parsers) {
            if(parser.getClass().equals(targetClass)){
                result = parser;
            }
        }
        return transformer;
    }

}
Run Code Online (Sandbox Code Playgroud)

更好的是,您可以添加Parser.isCompatibleWith(SomeInput input)方法来简化paser检测代码.


Kin*_*ngz 7

下面是服务定位器类的示例.这将从服务注册表返回给定ID的服务.注册表是MAP,如图所示自动装配.这是生产系统的一个工作示例:

@Service
public class MyServiceLocator {

    @Autowired
    private Map<String, MyService> myServiceRegistry;

    /**
     * Service locator to find the right Domain service to interact with the      requested  data store
     *   
     * @param serviceID
     * @return   
     */
    public MyService locateServiceFor(String serviceID) {
        //Using the Given string 'serviceID' as key, lookup the service from the Registry
        return myServiceRegistry.get(serviceID);
}
Run Code Online (Sandbox Code Playgroud)