Принудительно использовать сигнатуру метода с помощью аннотаций - PullRequest
1 голос
/ 19 февраля 2020

Я написал пользовательскую аннотацию, которую использую для поиска методов, которые можно вызывать через платформу IoT. Это аннотация уровня метода:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DirectMethod {

    String value();

}

Я смотрю эту аннотацию во время выполнения, и чтобы вызов был успешным, ожидаемая подпись должна быть:

@DeviceMethod("metod")
public ReturnType methodName(final String data) {...}

, т. Е. Тип возврата и входные параметры имеют решающее значение.

Есть ли способ сделать аннотацию "умной", если ее тип цели METHOD? Как встроенные предупреждения IDE и тому подобное. Или мне просто нужно обрабатывать каждую аннотацию вручную при запуске, и процедура запуска завершается неудачно, если какой-либо метод нарушает мой предполагаемый контракт метода?

1 Ответ

1 голос
/ 19 февраля 2020

Да, вы можете написать процессор аннотаций для проверки ваших вызовов, единственным недостатком этого является то, что процессоры аннотаций должны быть переданы в javac (Gradle и Maven поддерживают простой синтаксис для их регистрации), чтобы кто-то мог просто не делайте этого и не видите никаких предупреждений / ошибок.

Но в противном случае все, что вам нужно сделать, это создать специальную аннотацию и процессор, например:

@SupportedAnnotationTypes("com.gotofinal.direct.DirectMethod")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class DirectAnnProcessor extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        TypeElement stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String");
        TypeElement expectedReturnType = processingEnv.getElementUtils().getTypeElement("com.gotofinal.direct.ReturnType");

        for (Element element : roundEnv.getElementsAnnotatedWith(DirectMethod.class)) {
            if (! (element instanceof ExecutableElement)) {
                processingEnv.getMessager().printMessage(Kind.ERROR, "Annotation should be on method.");
                continue;
            }
            ExecutableElement executableElement = (ExecutableElement) element;
            if (! executableElement.getReturnType().equals(expectedReturnType)) {
                processingEnv.getMessager().printMessage(Kind.ERROR, "Method should return ReturnType");
            }
            List<? extends VariableElement> parameters = executableElement.getParameters();
            if (parameters.size() != 1 && parameters.get(0).asType().equals(stringType)) {
                processingEnv.getMessager().printMessage(Kind.ERROR, "Method should have single String argument");
            }
        }
        return true; // no further processing of this annotation type
    }
}

и зарегистрировать его в META-INF/services/javax.annotation.processing.Processor файле:

com.gotofinal.direct.DirectAnnProcessor

И тогда вы можете добавить такую ​​библиотеку в maven / gradle как процессор аннотаций, и она должна сообщать о любых проблемах. В Gradle такая библиотека должна быть добавлена ​​с помощью объявления annotationProcessor "my:lib:0.1".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...