2010-12-08 5 views
7

Ich hätte gerne eine JAR-Datei, in der nur das API-Paket zugänglich ist. Alle anderen Pakete (die Implementierungen enthalten) sind für ein anderes jar (oder für eine andere Klasse) nicht zugänglich.Java: Expose nur ein einzelnes Paket in einer JAR-Datei

Ist es möglich?

Wenn ja, wie?

+0

In der Regel werden Jars mit dem Befehl 'jar' erstellt. Ant-, Maven- und andere Build-Tools sind einfach Verschleierungsprobleme. –

+1

Vergesst das Bauwerkzeug nicht, jede Lösung könnte meine Bedürfnisse erfüllen. – glmxndr

+1

Zugriffskontrolle funktioniert in Java nicht so ... – Nate

Antwort

3

Derzeit für Java 8 geplant (2012?) Ist JSR 294. Dieser JSR führt bessere Modularisierungssprachenkonstrukte in Java ein.

Heute kann eine Implementierung in mehrere Pakete partitioniert werden. Teile einer solchen Implementierung müssen enger miteinander gekoppelt sein als mit der umgebenden Softwareumgebung. Designer sind heute gezwungen, Elemente des Programms, die von anderen Teilen der Implementierung benötigt werden, als öffentlich zu deklarieren - und damit global zugänglich zu machen, was eindeutig suboptimal ist.

Alternativ kann die gesamte Implementierung in einem einzigen Paket platziert werden. Dies löst das obige Problem, ist jedoch schwerfällig und macht alle Interna aller Unterteile zueinander verfügbar.

Die beabsichtigten Sprachänderungen werden diese Probleme beheben. Insbesondere erwarten wir, einen neuen Begriff von Modulen einzuführen (Superpackages) auf der Sprachebene, wo bestehende öffentliche Zugangskontrolle nur innerhalb eines Moduls auf Sprachniveau gelten würde und der Zugriff auf APIs von außerhalb eines Moduls auf APIs beschränkt wäre explizit exportiert.

Jetzt glaube ich, die Expertengruppe diskutiert noch die Details dieses Konzepts. Aber ich glaube, eine Sache, die Sie vielleicht in der Lage sein zu tun, das ist (Quelle: Super Packages in Java 7.0):

superpackage com.myorg.myApp.model 
{ 
    member package com.myorg.myApp.model.swing; 

    member package com.myorg.myApp.model.html; 

    export com.myorg.myApp.model.swing.SEmployee; 
    export com.myorg.myApp.model.swing.SDepartment; 

    export package com.myorg.myApp.model.html; 
} 

Mit anderen Worten, für einen gegebenen „superpackage“ können Sie definieren, was ist und nicht exportiert wird, unabhängig von der Sichtbarkeit Schlüsselwörter wie public.

+0

Hier ist ein Link zu Mark Reinholds Blog, der bizarr die maßgebliche Quelle für die Zukunft von Java zu sein scheint: http://blogs.sun.com/mr/entry/plan_b_details –

+0

Dieser JSR ist als inaktiv markiert und die letzte Aktivität war im Jahr 2007 - wird es wirklich passieren? – bacar

+0

die Verbindung zu Mark Reinholds Blog scheint zu funktionieren, hier ist ein aktualisiertes Paar: http://mreinhold.org/blog/module-system-requirements, http://mreinhold.org/blog/plan-b – bacar

1

In einer "normalen" Java-Anwendung ist das nicht möglich. In der OSGi-Umgebung definieren Sie jedoch, welche Pakete von Ihrem Bundle (leicht modifizierte JAR-Datei) für andere Bundles freigegeben werden und welche privat sind (außerhalb Ihres Bundles nicht sichtbar).

0

Warum nicht einfach ein Jar mit den API-Klassen und einem separaten Jar mit Implementierungen je nach API erstellen. Auf diese Weise können Sie Ihre API-Klassen verteilen, ohne Ihre Implementierung zu verteilen.

KR.

+0

Das machen wir gerade. Ich versuche nur, es in einem einzigen Glas zu machen, wenn möglich. – glmxndr

2

Dies ist in Java 6 nicht wirklich möglich, es sei denn, Sie verwenden OSGI, von dem ich annehme, dass Sie es nicht sind. was ich normalerweise tun, um Klassen zu verbergen, ist die Verwendung von Paket-freundlichen Klassen für Implementierungen - aber Sie müssen möglicherweise noch einige Klassen offenlegen, wenn Sie Implementierungsklassen leben in einem separaten Paket sind.

Beispiel:

package com.example;

public class Service { } nehmen die API-Klasse verwendet ServiceImpl wie es Implementierung ist

jetzt, wenn ServiceImpl wohnt im selben Paket, das Sie vielleicht entfernen es ist public class Modifikator und es wird nicht sein zugänglich außerhalb des Pakets ...

Wenn es in einem anderen Paket (Ihrem Fall) lebt, muss es öffentlich sein:

package com.example.impl;

public class ServiceImpl { }

aber alle Implementierungsdetails (bezogen Klassen verwendet es) aus dem gleichen Paket muss nicht öffentlich sein!

+0

Gibt es einen besonderen Grund, warum Sie das Kapital 'Y' auf 'Sie' setzen? Schöne Antwort trotzdem. :) – glmxndr

+1

@subtenante: Klar bist du Gott. '' –

+0

@subtenante Ich wurde so in der Schule gedacht - wollte nur höflich sein :) – kares

0

Ich kann den Grund sehen, warum Sie es tun möchten. Es hat mich immer beunruhigt, wenn ich versuche, jemandes Bibliothek zu benutzen. Es gibt so viele Klassen, von denen ich nicht weiß, wo ich anfangen soll.

Soweit ich aus den meisten Bibliotheken sehen kann, gibt es keine solche Bibliothek, die nicht verwandte Klassen zu verbergen versuchen. Obwohl dies kein solider Beweis ist, muss dies bedeuten, dass es keinen Weg gibt, dies zu tun. Normalerweise knüpfen sie API und die Implementierung in getrennte JAR-Dateien.

Wenn Sie Ihre Anwendung jedoch über das OSGi-Framework ausführen, ist es möglich, Ihre JAR-Datei so zu bündeln, dass der OSGi-Rahmen nur die gewünschten API-Klassen sehen kann. Aber die Verwendung von OSGi könnte ein wenig Arbeit sein.

0

Sie können eine ant-task- oder maven-jar-plugin-Konfiguration hinzufügen, um die benötigten Komponenten mit den von Ihnen gewünschten Bauwerkzeugeinstellungen zu füllen.

4

Wenn Sie Klassen haben, die nicht verwendet werden sollen, legen Sie sie in ein Unterpaket namens "internal". Das hindert andere nicht daran, die Klassen zu verwenden, aber es ist ein starkes Indiz dafür, dass dies nicht der Fall sein sollte.

Beispiel:

my.library.Stuff 
my.library.StuffFactory 
my.library.internal.StuffImpl 
my.library.internal.MoreStuff 
my.library.internal.xml.DataStuff 

Während dies keine wirkliche Lösung ist, würde ich es eine bewährte Methode in Betracht ziehen.

0

Eine andere Lösung besteht darin, den Standardzugriffsmodifikator in Implementierungsklassen festzulegen und sie in das gleiche Paket wie die Schnittstellen einzufügen. Obwohl es ein bisschen dreckig ist.

Verwandte Themen