我想隐藏API用户的服务(接口)的实现(具体类)。该实现由使用Java API ServiceLoader 机制的工厂提供给用户。此Loader要求实现类具有公共可见性。只要实现隐藏在用户不直接依赖的不同JAR(除了API JAR之外),就可以了。
但是,为了便于分发,使用默认实现的JAR内容将打包到API JAR中。因此,用户有效地依赖于此预先打包的JAR,其中默认实现类可用于公共可见性。没有什么能阻止人们直接实例化实现。我不希望那是可能的。
我的坏主意:
您认为正确的方法是什么?有任何妥协吗?
使用OSGi或其他重型机械是不可能的。
答案 0 :(得分:2)
令人失望但是:
<scope>runtime</scope>
。唯一的另一种方法是在javadoc中使用@Deprecated
,并使用java服务API作为注释如何使用相应的类。
答案 1 :(得分:1)
在C#中,您可以创建仅对相关好友程序集可见的内部接口,然后显式实现该接口。我不确定你将如何在Java中实现这一点,但从概念上讲,这就是我在.NET世界中解决这个问题的方法。
编辑我只是查了一下,据我所知,Java没有明确的接口实现。作为FYI,接口的显式实现要求您通过接口成员进行函数调用,不能将其称为实现类的成员。这就是为什么我的技术适合我,至少在.NET世界中。
或者,我建议将接口放在另一个JAR中,而不是用API分发它
答案 2 :(得分:0)
您无法轻易阻止人们实例化/访问任何已发布的类。
因此,我可能只是简单地包装您正在使用的ServiceLoader
机制,并提供通过Java接口引用的实例化类(而不是作为具体的实现引用)。
答案 3 :(得分:0)
我更喜欢您的第一种方法,将实现类包设为私有,并使用ServiceLoctor检索特定服务。在我的项目中,包结构如下:
-package
|-ServiceInterface(public)
|-ServiceImplementation(default,package private)
|-ServiceLocator(public)
serviceLocator是这样的:
public class ServiceLocator{
private static final Map<String,Service> services;
static {
services=new HashMap<String,Service>();
services.put("default",new ServiceImplementation());//hide implementation
}
public Service getService(String name){
return services.get(name);
}
public registerService(Service service, String name){
services.put(name,service)
}
}
最终用户无权访问实现类,稍后您可以轻松更改为使用其他实现类。