2014-12-22 5 views
9

Java 8 имеет функцию, называемую аннотациями типа (JSR 308). Я хотел бы использовать его для простой структуры Object Mapper. Я хотел бы определить аннотаций @ExpectedType как этотКак использовать аннотации пользовательского типа в Java

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

И затем использовать его в своем коде, как это:

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

IObjectA является интерфейс, реализуемый классами ObjectA_DTO и ObjectA_Entity. Услуга Я хотел бы использовать этот способ:

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

Я хотел бы изменить вызов методов SomeServiceImpl использовать картограф Object. Это может быть достигнуто сгенерированным кодом с использованием JSR 269 или AOP.

Проблема в том, что я написал простой обработчик аннотаций и вообще не обрабатывает аннотации типов. Источник простой аннотации процессор выглядит следующим образом:

@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; 
    } 
} 

Любые идеи, как использовать или как получить доступ к аннотацию типа с помощью SimpleAnnotationsProcessor? Использование API совместимой обработки аннотаций для меня не требуется. Я думаю, что он будет иметь лучшую производительность, чем отражение Java. Во всяком случае, я не знаю, как получить доступ к аннотации типов через Java Reflection.

+0

Я предполагаю, что я не ясно, какую цель вы пытаетесь достичь. Почему бы просто не сделать подпись метода 'ObjectA_DTO doSomething (ObjectA_Entity)', если это то, что вы ожидаете от нее? –

+0

Подпись метода не может быть так, потому что я хотел бы использовать служебный экземпляр, как этот 'someService.doSomething (новый ObjectA_DTO())'. Я хочу, чтобы объект mapper сопоставил 'ObjectA_DTO' с' ObjectA_Entity' и аннотацию типа @ExpectedType определяет тип назначения. Это причина, почему подпись должна быть «IObjectA doSomething (IObjectA)». –

+0

Я просто поймал ваш вопрос попутно ... Я сделал семестр проекта по разработке линейки продуктов, где мы обработали аннотации. На данный момент я оставлю вас с этим важным учебным пособием, который действительно заставил меня заняться этим вопросом (вы можете пропустить часть 3 о генерации кода) - https://deors.wordpress.com/2011/09/26/annotation-types/ позже я перепроверку этого поста для прогресса. – ThisClark

ответ

2

Я не уверен, я понимаю, что вы пытаетесь достичь, но вот пример того, как вы можете получить доступ к аннотациям с Reflection API Java:

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

Выход выглядит следующим образом:

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

Обратите внимание, что не все возможные аннотации типов доступны через отражение api, но вы всегда можете прочитать их из байтового кода (см. Мой ответ here).

+0

Я хотел бы сделать это с помощью процессора аннотаций, потому что он может быть быстрее во время выполнения, а затем отражать, так или иначе, я принимаю ваш ответ. Framework Checker может читать аннотации типов из обработчика аннотаций (не из байтового кода). Вы знаете, как это происходит? –

+0

К сожалению, я еще не использовал Checker framework. Я не считаю, что обработчики аннотаций будут быстрее, чем использование рефлексии (не уверен, хотя). Но я не буду думать о каких-либо оптимизации, прежде чем приступать к фактическим проблемам производительности. Обычно отражение достаточно быстро ... – Balder

+0

Вы знаете, как получить доступ к аннотациям типа для типов, используемых с локальными переменными через API отражения? Что-то вроде этого '@NotNull String str =" ";' или 'String str = (@Nullable String) null;' внутри тела метода? Я хотел бы использовать аннотацию '@ ExpectedType' следующим образом:' ObjectA_DTO aDto = (@ExpectedType ObjectA_DTO) someService.doSomething (...); ' –

0

Я думаю, что вы смешиваете использование аннотаций во время выполнения по сравнению с использованием одного и того же при компиляции различными инструментами. Интерфейс Processor предназначен для использования в инструментах (компилятор, генератор javadoc), а не в вашем коде выполнения.

+0

Я хочу сгенерировать код для лучшей производительности, такой как MapStruct или Lombok, а не используя java-отражение во время выполнения. –

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

    public String identifier() default ""; 

} 

@SearchDefinition - может быть использован в любом месте

+1

Этот ответ совершенно не прав '@Target (ElementType.FIELD)' аннотация не может использоваться нигде. Он может использоваться только с полями класса. Если '@ Target' опущен, его можно использовать почти везде, кроме типа cast (' (@SearchDefinition String) "abc" ') или общего типа (' List <@SearchDefinition String> '). –

 Смежные вопросы

  • Нет связанных вопросов^_^