2017-10-10 2 views
0

Ich muss eine einzelne App mit zwei verschiedenen Anwendungen verbinden. Die erste Anwendung verwendet das Protokoll P in der Version 1, das zweite verwendet das gleiche Protokoll in der Version 2. Die Bibliotheken sind inkompatibel, daher muss ich beide in meiner App verwenden. Das Problem besteht darin, dass sie dasselbe Paket verwenden, z. com.company.P und Architektur (Klassennamen, Pakete) sind gleich.Zwei Versionen derselben Bibliothek mit demselben Paketnamen in einer Anwendung

Ist es möglich, beide in derselben App zu verwenden?

+0

Ja: zwei ClassLoader verwenden –

+0

@MauricePerry Wie? Jedes Beispiel wäre nützlich. – Trismegistos

Antwort

1

Hier ist ein sehr einfaches Beispiel: Sie ein Glas für die Hauptanwendung benötigen, in dem Sie eine Schnittstelle Dienst definieren:

package multiverse; 

public interface Service { 
    public String getDescription(); 
} 

und eine Hauptklasse erstellt eine Instanz des Dienstes von den Gläsern in zwei verschiedene Verzeichnisse:

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()); 
     } 
    } 
} 

Jetzt habe ich zwei Implementierungen des Dienstes, in zwei verschiedene Gläser, eine in jedem der Verzeichnisse, die von dem Programm verwendet oben:

package multiverse; 

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

und

package multiverse; 

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

Beachten Sie, dass sie Zugriff auf die Service-Schnittstelle haben müssen, wenn sie der Kompilierung sind. Diese Schnittstelle kann sich im gleichen Jar wie das Hauptprogramm oder in einem separaten Jar befinden. Das Hauptprogramm kann nicht direkt auf die Klassen der Jars zugreifen, die für jede Implementierung verwendet werden: Es muss immer über eine Schnittstelle gehen.

+0

Leider ist mein Fall, dass ich keine Schnittstelle habe. Ich habe zwei Klassen mit demselben qualifizierten Namen in zwei verschiedenen Gläsern. – Trismegistos

+0

@Trismegistos OK, schreibe eine Schnittstelle –

+0

Ich kann nicht, weil diese Bibliotheken nicht von mir zur Verfügung gestellt werden. – Trismegistos

Verwandte Themen