在一个应用程序中具有相同包名称的同一个库的两个版本

时间:2017-10-10 08:25:45

标签: java package

我需要将单个应用程序连接到两个不同的应用程序。第一个应用程序在版本1中使用协议P第二个在版本2中使用相同的协议。库是不兼容的,所以我必须在我的应用程序中使用这两个。问题是他们使用相同的包装,例如com.company.P和架构(类名,包)是相同的。

是否可以在同一个应用中同时使用它们?

1 个答案:

答案 0 :(得分:1)

这是一个非常简单的示例:您的主应用程序需要一个jar,您可以在其中定义一个接口Service:

package multiverse;

public interface Service {
    public String getDescription();
}

Main类从两个不同目录中的jar创建服务实例:

package multiverse;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Main {
    private static final Logger LOG = Logger.getLogger(Main.class.getName());
    private static final File DIR1
            = new File("../multiverse-v1/dist");
    private static final File DIR2
            = new File("../multiverse-v2/dist");

    public static void main(String[] args) {
        Service service1 = loadService(DIR1);
        Service service2 = loadService(DIR2);
        System.out.println(service1.getDescription());
        System.out.println(service2.getDescription());
    }

    private static Service loadService(File dir) {
        try {
            File[] jars = dir.listFiles((File file) -> file.isFile()
                    && file.getName().toLowerCase().endsWith(".jar"));
            URL[] urls = new URL[jars.length];
            for (int i = 0; i < jars.length; ++i) {
                urls[i] = jars[i].toURI().toURL();
            }
            ClassLoader cl = new URLClassLoader(urls);
            Class<? extends Service> clazz
                    = (Class<? extends Service>) cl.loadClass(
                            "multiverse.ServiceImpl");
            return clazz.newInstance();
        } catch (MalformedURLException | ClassNotFoundException
                | InstantiationException | IllegalAccessException ex) {
            LOG.log(Level.SEVERE, null, ex);
            throw new RuntimeException(ex.getMessage());
        }
    }
}

现在我在两个不同的jar中有两个服务实现,在上面程序使用的每个目录中都有一个:

package multiverse;

public class ServiceImpl implements Service {
    @Override
    public String getDescription() {
        return "Service V1";
    }
}

package multiverse;

public class ServiceImpl implements Service {
    @Override
    public String getDescription() {
        return "Service V2";
    }    
}

请注意,在编译时,它们必须能够访问Service接口。此接口可以与主程序位于同一个jar中,也可以位于单独的jar中。主程序无法直接访问用于每个实现的jar类:它必须始终通过接口。