2014-12-22 49 views
9

Java 8 ma funkcję o nazwie Adnotacje typu (JSR 308). Chciałbym użyć go do prostego systemu mapowania obiektów do obiektu. Chciałbym określić adnotacji @ExpectedType jak tenSposób korzystania z adnotacji typu niestandardowego w Javie

@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface ExpectedType { 
    public Class<?> value(); 
} 

a następnie używać go w moim kodu tak:

public class SomeServiceImpl() { 
    public @ExpectedType(ObjectA_DTO.class) IObjectA doSomething(@ExpectedType(ObjectA_Entity.class) IObjectA obj) { 
     return (ObjectA_Entity) obj; // it's correct 
    } 
} 

IObjectA jest realizowany przez interfejs klas ObjectA_DTO i ObjectA_Entity. Usługa Chciałbym wykorzystać ten sposób:

// it's correct 
assert someService.doSomething(new ObjectA_DTO()).getClass() == ObjectA_DTO.class; 

chciałbym zmiana połączenia metod SomeServiceImpl użyć mapowania obiektów. Można to osiągnąć za pomocą wygenerowanego kodu przy użyciu JSR 269 lub AOP.

Problem polega na tym, że napisałem prosty procesor adnotacji i w ogóle nie obsługuję adnotacji typu. Źródłem prosty procesor adnotacji wygląda następująco:

@SupportedAnnotationTypes("*") 
@SupportedSourceVersion(SourceVersion.RELEASE_8) 
public class SimpleAnnotationsProcessor extends AbstractProcessor { 

    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 
     Messager messager = processingEnv.getMessager(); 
     try { 
      for (TypeElement e : annotations) { 
       messager.printMessage(Diagnostic.Kind.NOTE, e.toString()); 
       for (Element elem : roundEnv.getElementsAnnotatedWith(e)) { 
        messager.printMessage(Diagnostic.Kind.NOTE, elem.toString()); 
       } 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     return true; 
    } 
} 

pomysłów jak wykorzystać lub uzyskiwania dostępu typu adnotacji przez SimpleAnnotationsProcessor? Używanie Pluggable Adnotation Processing API nie jest dla mnie konieczne, myślę, że miałoby lepszą wydajność niż odbicie Java. W każdym razie nie wiem jak uzyskać dostęp do adnotacji typu za pomocą Java Reflection.

+0

Chyba jestem jasne, co cel starasz się osiągnąć. Czemu po prostu nie utworzyć sygnatury metody 'ObjectA_DTO doSomething (ObjectA_Entity)' jeśli tego oczekujesz? –

+0

Podpis metody nie może być taki, ponieważ chciałbym użyć instancji usługi takiej jak ta 'someService.doSomething (new ObjectA_DTO())'. Chcę, aby obiekt mapujący obiekt zamapował obiekt 'ObjectA_DTO' na' ObjectA_Entity', a typ adnotacji @ExpectedType określa typ miejsca docelowego. To jest powód, dla którego podpis musi być 'IObjectA doSomething (IObjectA)'. –

+0

Właśnie przechwyciłem twoje pytanie ... Zrobiłem semestralny projekt dotyczący rozwoju linii produktów, w którym przetwarzaliśmy adnotacje. Na razie opowiem Ci o tym ważnym samouczku, który naprawdę mnie poruszył (możesz pominąć część trzecią o generowaniu kodu) - https://deors.wordpress.com/2011/09/26/annotation-types/ później ponownie sprawdzę ten post, aby uzyskać postęp. – ThisClark

Odpowiedz

2

Nie jestem pewien, czy rozumiem co próbujesz osiągnąć, ale tutaj jest przykładem, w jaki sposób można uzyskać dostęp do notatek z refleksji Java API:

package test; 

import java.lang.annotation.Annotation; 
import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 
import java.lang.reflect.AnnotatedType; 
import java.lang.reflect.Method; 

public class TypeParameterTest { 

    @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) 
    @Retention(RetentionPolicy.RUNTIME) 
    public @interface ExpectedType { 
     public Class<?> value(); 
    } 

    public static interface IObjectA {} 

    public static class ObjectA_DTO implements IObjectA {} 

    public static class ObjectA_Entity implements IObjectA {} 

    public static class SomeServiceImpl { 
     public @ExpectedType(ObjectA_DTO.class) IObjectA doSomething(@ExpectedType(ObjectA_Entity.class) IObjectA obj) { 
      return (ObjectA_Entity) obj; 
     } 
    } 

    public static void main(String[] args) throws NoSuchMethodException, SecurityException { 
     Method m = SomeServiceImpl.class.getMethod("doSomething", IObjectA.class); 
     AnnotatedType returnType = m.getAnnotatedReturnType(); 
     Annotation returnTypeAnnotation = returnType.getAnnotation(ExpectedType.class); 
     System.out.println(returnTypeAnnotation); 

     AnnotatedType[] parameters = m.getAnnotatedParameterTypes(); 
     for (AnnotatedType p : parameters) { 
      Annotation parameterAnnotation = p.getAnnotation(ExpectedType.class); 
      System.out.println(parameterAnnotation); 
     } 
    } 
} 

Wyjście wygląda następująco:

@test.TypeParameterTest$ExpectedType(value=class test.TypeParameterTest$ObjectA_DTO) 
@test.TypeParameterTest$ExpectedType(value=class test.TypeParameterTest$ObjectA_Entity) 

Pamiętaj, że nie wszystkie możliwe adnotacje typu są dostępne za pośrednictwem api odbicia, ale zawsze możesz je odczytać z kodu bajtowego, jeśli to konieczne (zobacz moją odpowiedź: here).

+0

Chciałbym to zrobić za pomocą procesora adnotacji, ponieważ może on być szybszy w środowisku wykonawczym niż odbicie, w każdym razie akceptuję twoją odpowiedź. Struktura Checker może czytać adnotacje typu z procesora adnotacji (nie z kodu bajtowego). Czy wiesz, jak to działa? –

+0

Niestety, jeszcze nie korzystałem z frameworka Checker. Nie wierzę, że procesory adnotacji byłyby szybsze niż za pomocą refleksji (nie jestem pewien). Ale nie pomyślałbym o żadnych optymalizacjach przed uruchomieniem rzeczywistych problemów z wydajnością. Zwykle odbicie jest wystarczająco szybkie ... – Balder

+0

Czy wiesz, jak uzyskać dostęp do adnotacji typu dla typów używanych ze zmiennymi lokalnymi za pomocą interfejsu API Reflect? Coś takiego: '@NotNull String str =";; 'lub' String str = (@Nullable String) null; 'wewnątrz ciała metody? Chciałbym użyć adnotacji '@ ExpectedType' w następujący sposób:' ObjectA_DTO aDto = (@ExpectedType ObjectA_DTO) someService.doSomething (...); ' –

0

Myślę, że mieszasz użycie adnotacji w czasie wykonywania w porównaniu do użycia tego samego w czasie "kompilacji" przez różne narzędzia. Processor Interfejs jest przeznaczony do użycia w narzędziach (kompilator, generator javadoc), a nie w kodzie środowiska wykonawczego.

+0

Chcę wygenerować kod dla lepszej wydajności, na przykład MapStruct lub Lombok zamiast używanie refleksji java w środowisku wykonawczym. –

0
@Documented 
@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.FIELD) 
public @interface SearchDefinition { 

    public String identifier() default ""; 

} 

@SearchDefinition - może być stosowany wszędzie

+1

Ta odpowiedź jest całkowicie błędna '@Target (ElementType.FIELD)' adnotacja nie może być nigdzie używana. Można go używać tylko z polami klasy. Jeśli '@ Cel' zostanie pominięty, można go użyć prawie wszędzie, z wyjątkiem typu rzutowania (' (@SearchDefinition String) "abc" ') lub typu ogólnego (' List <@SearchDefinition String> '). –