2. ServiceLoader
Java 开发人员经常希望将使用和创建组件的内容区分开来。这通常是通过创建一个描述组件动作的接口,并使用某种中介创建组件实例来完成的。很多开发人员使用 Spring 框架来完成,但还有其他的方法,它比 Spring 容器更轻量级。
java.util 的 ServiceLoader 类能读取隐藏在 JAR 文件中的配置文件,并找到接口的实现,然后使这些实现成为可选择的列表。例如,如果您需要一个私仆(personal-servant)组件来完成任务,您可以使用清单 2 中的代码来实现:
清单 2. IPersonalServant
public interface IPersonalServant { // Process a file of commands to the servant public void process(java.io.File f) throws java.io.IOException; public boolean can(String command); } |
can() 方法可让您确定所提供的私仆实现是否满足需求。清单 3 中的 ServiceLoader 的 IPersonalServant 列表基本上满足需求:
清单 3. IPersonalServant 行吗?
import java.io.*; import java.util.*; public class Servant { public static void main(String[] args) throws IOException { ServiceLoader<IPersonalServant> servantLoader = ServiceLoader.load(IPersonalServant.class); IPersonalServant i = null; for (IPersonalServant ii : servantLoader) if (ii.can("fetch tea")) i = ii; if (i == null) throw new IllegalArgumentException("No suitable servant found"); for (String arg : args) { i.process(new File(arg)); } } } |
假设有此接口的实现,如清单 4:
清单 4. Jeeves 实现了 IPersonalServant
import java.io.*; public class Jeeves implements IPersonalServant { public void process(File f) { System.out.println("Very good, sir."); } public boolean can(String cmd) { if (cmd.equals("fetch tea")) return true; else return false; } } |