ďťż
 
annotations ďťż
 
annotations
Zobacz wiadomości
 
Cytat
A gdyby tak się wedrzeć na umysłów górę, / Gdyby stanąć na ludzkich myśli piramidzie, / I przebić czołem przesądów chmurę, / I być najwyższą myślą wcieloną. . . Juliusz Słowacki, Kordian
Indeks BCB i MySQL subiekt gt fototapeta
 
  Witamy

annotations



Leonard Milcin Jr. - 06-07-2007 00:04
annotations
  Witam!

Czy któryś z grupowiczów orientuje się w jaki sposób można uzyskać listę
klas zawierających konkretną adnotację?

Np. mam sobie coś takiego:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Plugin {

String value();

}

oraz klasę:

@Plugin("testTask")
public class TestTask extends BaseTask {

}

W jaki sposób mogę gdzieś indziej uzyskać (np. wylistować) wszystkie
klasy z załączoną adnotacją @Plugin? Zakładam oczywiście, że pluginy w
tym wypadku znajdują się w classpath.

Pozdrawiam,
Leonard





Artur Zabronski - 06-07-2007 00:04

  Leonard Milcin Jr. wrote:
>
> W jaki sposób mogę gdzieś indziej uzyskać (np. wylistować) wszystkie
> klasy z załączoną adnotacją @Plugin? Zakładam oczywiście, że pluginy w
> tym wypadku znajdują się w classpath.
>
IMHO nie ma takiej możliwości, najlepszym sposobem chyba jest pobranie
listy plików .class np z JARa ładowanie ich poprzez Class.forName() i
sprawdzanie czy zawiera taką adnotację.

--
Pozdrawiam,
Artur




Leonard Milcin Jr. - 06-07-2007 00:04

  Artur Zabronski wrote:
> Leonard Milcin Jr. wrote:
>>
>> W jaki sposób mogę gdzieś indziej uzyskać (np. wylistować) wszystkie
>> klasy z załączoną adnotacją @Plugin? Zakładam oczywiście, że pluginy w
>> tym wypadku znajdują się w classpath.
>>
> IMHO nie ma takiej możliwości, najlepszym sposobem chyba jest pobranie
> listy plików .class np z JARa ładowanie ich poprzez Class.forName() i
> sprawdzanie czy zawiera taką adnotację.
>

Hmm... tak mi się wydawało bo w sumie klasa nie powinna być ładowana
zanim nie zostanie gdzieś użyta. Wskazywałby na to np. fakt, że bloki
static{} są wykonywane gdy klasa jest pierwszy raz użyta gdzieś w kodzie.

Z drugiej jednak strony wiele frameworków robi właśnie dokładnie to. Np.
JPA w jakiś sposób dostaję listę klas zawierającą adnotację @Entity,
etc. Myślałem, że może istnieje jakiś prosty sposób...

Pozdrawiam,
Leonard




Artur Zabronski - 06-07-2007 00:04

  Leonard Milcin Jr. wrote:
>
> Hmm... tak mi się wydawało bo w sumie klasa nie powinna być ładowana
> zanim nie zostanie gdzieś użyta. Wskazywałby na to np. fakt, że bloki
> static{} są wykonywane gdy klasa jest pierwszy raz użyta gdzieś w kodzie.
>
Również można to wywnioskować po ClassNotFoundException dopiero w
momencie użycia :-)
> Z drugiej jednak strony wiele frameworków robi właśnie dokładnie to. Np.
> JPA w jakiś sposób dostaję listę klas zawierającą adnotację @Entity,
> etc. Myślałem, że może istnieje jakiś prosty sposób...
>
W JPA standalone musisz w persistence.xml wskazać klasy-encje poprzez
znacznik class np <class>foo.bar.MyEntity</class>, w JPA z EJB po prostu
serwer aplikacji sprawdza każdą klasę w archiwum EJB i rozpoznaje EJB i
encje.

Sprawdziłem w źródłach GlassFish-a i jest właśnie tak, są szukane .class
i ładowane przez URL-a a później sprawdzane jest czy klasa zawiera
odpowiednie adnotacje.

--
Pozdrawiam,
Artur





Jacek Laskowski - 06-07-2007 00:04

  Artur Zabronski wrote:

> Sprawdziłem w źródłach GlassFish-a i jest właśnie tak, są szukane .class
> i ładowane przez URL-a a później sprawdzane jest czy klasa zawiera
> odpowiednie adnotacje.

Jest jeszcze inny sposób, ale nie mogę sobie teraz przypomnieć.
Ładowanie klas powoduje odłożenie ich na PermGen, więc dla wielu klas a
niewielu encji może to być kosztowne pamięciowo. W xbean-reflect wydaje
mi się, że jest efektywniejszy sposób niż Class.forName, ale za późno,
żebym sobie przypomniał.

Pewnie Piotr Kobzda - spec od asm/cglib - wiedziałby jakie mamy
faktycznie efektywniejsze sposoby, ale temat annotations to pewnie go
nie zainteresuje. Ale jak umieściłoby się "asm/cglib do bani", czy
podobnie to, kto wie. ;-)

Jacek

--
Jacek Laskowski
http://www.JacekLaskowski.pl




Artur Zabronski - 06-07-2007 00:06

  Jacek Laskowski wrote:
>
> Jest jeszcze inny sposób, ale nie mogę sobie teraz przypomnieć.
> Ładowanie klas powoduje odłożenie ich na PermGen, więc dla wielu klas a
> niewielu encji może to być kosztowne pamięciowo. W xbean-reflect wydaje
> mi się, że jest efektywniejszy sposób niż Class.forName, ale za późno,
> żebym sobie przypomniał.
>
Nie mam czasu sprawdzać ale może jest to rozwiązane przez bezpośrednie
odczytanie pliku klasy i podglądniecie jego struktury bez ładowania jej
do JVM? To odkładanie klas w PermGen można doświadczyć w połączeniu
Tomcat + Hibernate przy kilkunastu przeładowaniach aplikacji występuje
OOM PermGen space i trzeba restartować Tomcata.

--
Pozdrawiam,
Artur




Piotr Kobzda - 07-07-2007 00:03

  Jacek Laskowski wrote:

> Ładowanie klas powoduje odłożenie ich na PermGen, więc dla wielu klas a
> niewielu encji może to być kosztowne pamięciowo.

Czy to PermGen, czy gdzieś indziej, to nie ma tu znaczenia, klas których
jeszcze nie wczytano nie znajdziesz w runtime.

> W xbean-reflect wydaje
> mi się, że jest efektywniejszy sposób niż Class.forName, ale za późno,
> żebym sobie przypomniał.

Jeśli tylko wśród załadowanych klas szukać, to czasem efektywniejsza
może okazać się instrumentacja (Instrumentation.getAllLoadedClasses()),
choć niekoniecznie musi tak też być -- np. gdy interesują nas klasy
tylko pewnego class-loader'a. Poza tym Class.forName() pozwala także
odszukać klasy jeszcze niezaładowane, więc efektywność nie ma tu w
zasadzie większego znaczenia (można by tu co najwyżej zasugerować
jeszcze użycie wariantu Class.forName() z initialize=false, co
niepotrzebnych inicjalizacji klas pozwoliłoby uniknąć, choć to mało
ważny drobiazg wydaje mi się już...).

> Pewnie Piotr Kobzda - spec od asm/cglib - wiedziałby jakie mamy
> faktycznie efektywniejsze sposoby, ale temat annotations to pewnie go
> nie zainteresuje.

Heh, interesuje, a jakże. :) Trudno jednak dodać coś do tematu, który
właściwe został już wyczerpany... :)

Możliwości są tu generalnie dwie:
1) wywnioskować z CLASSPATH jakie klasy znajdują się w otoczeniu i
wszystkie je przeanalizować;
2) dostarczyć gotowej listy klas, które mają oczekiwane własności (w
postaci pliku, rozszerzenia manifestu, jakiejś specjalnej klasy ...).

Możliwość 1) została już dość szczegółowo opisana, dodać można jedynie,
że właśnie ASM ładnie może wspomóc analizę class-file'i bez ich
ładowania (o czym Artur wspomniał). Zawsze jednak będzie to metoda
niedoskonała, gdyż mocno zależy od otoczenia, ograniczając jednocześnie
możliwości dostarczania klas JVMie.

Osobiście bardziej skłaniałbym się zatem do 2), zwłaszcza, że listę taką
można sobie wygodnie generować w czasie kompilacji prostym procesorem
adnotacji (patrz: javax.annotation.processing).

piotr




Piotr Lipski - 07-07-2007 00:03

  > Czy któryś z grupowiczów orientuje się w jaki sposób można uzyskać listę
> klas zawierających konkretną adnotację?
>
> Np. mam sobie coś takiego:
>
> @Retention(RetentionPolicy.RUNTIME)
> @Target(ElementType.TYPE)
> public @interface Plugin {
>
> String value();
>
> }
>
> oraz klasę:
>
> @Plugin("testTask")
> public class TestTask extends BaseTask {
>
> }
>
> W jaki sposób mogę gdzieś indziej uzyskać (np. wylistować) wszystkie
> klasy z załączoną adnotacją @Plugin? Zakładam oczywiście, że pluginy w
> tym wypadku znajdują się w classpath.

można to zrobić tak jak poniżej. U mnie działa ;-)

PL

import java.lang.annotation.Annotation;

import javax.tools.*;
import java.util.*;
import java.io.*;
import javax.annotation.processing.*;
import javax.lang.model.element.*;
import javax.lang.model.util.*;
import javax.lang.model.type.*;
import static javax.lang.model.SourceVersion.*;
import static java.util.Arrays.*;
import static java.util.Collections.*;

public class ListPlugins {
public static void main(String[] args) throws Exception {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
final StandardJavaFileManager fileManager =
compiler.getStandardFileManager(null, null, null);

fileManager.setLocation(StandardLocation.CLASS_PAT H, asList(new
File("plugins.jar")));//, new File("../../annotations_classes")));
final Iterable<JavaFileObject> jfos =
fileManager.list(StandardLocation.CLASS_PATH, "",
EnumSet.of(JavaFileObject.Kind.CLASS), true);
List<String> classes = new ArrayList<String>(){{
for(JavaFileObject jfo : jfos)
add(fileManager.inferBinaryName(StandardLocation.C LASS_PATH,
jfo));
}};

List<String> options = asList(/*"-verbose",*/ "-classpath",
"plugins.jar;../../annotations_classes");
JavaCompiler.CompilationTask task = compiler.getTask(null, null,
null, options, classes, null);

@SupportedSourceVersion(RELEASE_6)
@SupportedAnnotationTypes("*")
class MyProcessor extends AbstractProcessor {
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnvironment) {
if (!roundEnvironment.processingOver()) {
final Elements elements =
processingEnv.getElementUtils();
final Types types = processingEnv.getTypeUtils();
DeclaredType annotationTypeElement =
types.getDeclaredType(processingEnv.getElementUtil s().getTypeElement("pl.Plugin"));

Set<Element> result = Collections.emptySet();
ElementScanner6<Set<Element>, DeclaredType> scanner =
new ElementScanner6<Set<Element>, DeclaredType>(result){
Set<Element> annotatedElements = new
LinkedHashSet<Element>();

@Override
public Set<Element> scan(Element e, DeclaredType p)
{
java.util.List<? extends AnnotationMirror>
annotationMirrors =
processingEnv.getElementUtils().getAllAnnotationMi rrors(e);
for (AnnotationMirror annotationMirror :
annotationMirrors) {
if
(annotationMirror.getAnnotationType().equals(p))
annotatedElements.add(e);
}
e.accept(this, p);
return annotatedElements;
}
};

for (Element element :
roundEnvironment.getRootElements()) {
result = scanner.scan(element,
annotationTypeElement);
}

System.out.println(result);
}
return false;
}
}

task.setProcessors(asList(new MyProcessor()));
task.call();

fileManager.close();
}
}




Piotr Kobzda - 07-07-2007 00:03

  Piotr Lipski wrote:

> można to zrobić tak jak poniżej. U mnie działa ;-)

Jeśli jeszcze Filer'a dorzucić, to może i nie tylko u Ciebie będzie
potem działać... ;-)

Tak nawiasem jeszcze drobna rada dla OP: procesor adnotacji można wpiąć
wprost do javac'a (opcja -processor), lub do apt'a, wtedy pozostanie już
tylko to w środku... :)

piotr




lipski@gmail.com - 07-07-2007 00:03

  On Jul 6, 2:43 am, Piotr Kobzda <p...@gazeta.pl> wrote:
> Piotr Lipski wrote:
> > można to zrobić tak jak poniżej. U mnie działa ;-)
>
> Jeśli jeszcze Filer'a dorzucić, to może i nie tylko u Ciebie będzie
> potem działać... ;-)
>
> Tak nawiasem jeszcze drobna rada dla OP: procesor adnotacji można wpiąć
> wprost do javac'a (opcja -processor), lub do apt'a, wtedy pozostanie już
> tylko to w środku... :)
>
> piotr

Filer tu do niczego nie jest potrzebny. Chyba, że nie zrozumiałem
Twojej intencji. Jeśli miałeś na myśli, że wygląda to skomplikowanie -
zgadzam się - może ktoś zaproponuje coś prostszego.

PL




Piotr Kobzda - 07-07-2007 00:03

  lipski@gmail.com wrote:

> Filer tu do niczego nie jest potrzebny. Chyba, że nie zrozumiałem
> Twojej intencji. Jeśli miałeś na myśli, że wygląda to skomplikowanie -
> zgadzam się - może ktoś zaproponuje coś prostszego.

Chodziło mi realizację mojej sugestii w odrębnej gałęzi tego wątku.
Czyli zapis znalezionych przez procesor klas do np. pliku .properties,
po to by w przyszłości odczytać je za jednym zamachem (bez szukania w
runtime).

piotr




Artur Zabronski - 07-07-2007 00:03

  Piotr Kobzda wrote:
>
> Chodziło mi realizację mojej sugestii w odrębnej gałęzi tego wątku.
> Czyli zapis znalezionych przez procesor klas do np. pliku .properties,
> po to by w przyszłości odczytać je za jednym zamachem (bez szukania w
> runtime).
>
Jeszcze na myśl przychodzi mi taki pomysł: utworzyć instancje class
loadera, nim ładować te klasy i sprawdzać pod jakimś kątem a na końcu go
zwolnić i wtedy klasy załadowane przez niego również chyba zostaną
zwolnione?

--
Pozdrawiam,
Artur




Piotr Kobzda - 07-07-2007 00:03

  lipski@gmail.com wrote:

> Filer tu do niczego nie jest potrzebny. Chyba, że nie zrozumiałem
> Twojej intencji. Jeśli miałeś na myśli, że wygląda to skomplikowanie -
> zgadzam się - może ktoś zaproponuje coś prostszego.

Ha! Ja teraz dopiero widzę Twoją intencję ;) jest jednak nieco inna od
mojej... :)

Nie przyjrzałem się dokładnie jak budujesz JavaCompiler, przyjmując, że
przetwarzasz źródła (ja dotąd, tylko tak go używałem), a Ty pokazałeś
jak nim przetwarzać adnotowane klasy, wybacz. :-)

W ramach powrotu do rozmowy o tym samym ;) poniżej propozycja nieco
prostszego wydaje mi się procesora. U mnie działa, mam nadzieję, że u
Ciebie też? :-)

piotr

@SupportedAnnotationTypes("pl.Plugin")
@SupportedSourceVersion(RELEASE_6)
class MyProcessor extends AbstractProcessor {

@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
new ElementScanner6<Void, Void>() {

@Override
public Void visitType(TypeElement e, Void p) {
Plugin a = e.getAnnotation(Plugin.class);
if (a != null) {
System.out.println(a + " " + e.getQualifiedName());
}
return super.visitType(e, p);
}

}.scan(roundEnv.getRootElements(), null);
return false;
}
}
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • effulla.pev.pl
  • comp
    [PGSQL] Strumienie np. dla ostrzeżeń w procedurach Pl Pg SQL [mysql] grupowanie wierszy =?iso-8859-2?q?Problem_z_redefinicjami_makr_i_wielko=B6ci_w_f unkcji_C_dla_Postgresa?= [FoxPro] Kupię Microsoft FoxPro 2.6 for DOS sql zapytanie o czas sortowanie order by [OT]Pomoc w kupnie zdjęć shop cs2, przezroczyste warstwy DB2 / AS400 narzędzia mapa swiata w formacie wektorowym -potrzebne
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • marcelq.xlx.pl
  • Cytat

    Decede mihi sole - nie zasłaniaj mi słonca.
    Gdy kogoś kochasz, jesteś jak stworzyciel świata - na cokolwiek spojrzysz, nabiera to kształtu, wypełnia się barwą, światłem. Powietrze przytula się do ciebie, choćby był mróz, a ty masz w sobie tyle radości, że musisz ją rozdawać wokoło, bo się w tobie nie mieści
    Hoc fac - tak czyń.
    A tergo - od tyłu; z tyłu.
    I czarne włosy posiwieją. Safona

    Valid HTML 4.01 Transitional

    Free website template provided by freeweblooks.com