Ответ 1
Вы можете построить для этого обработчик аннотации. Обработчики аннотаций - это плагины компилятора, которые запускаются во время компиляции. Их ошибки обнаруживаются как ошибки компилятора и могут даже остановить сборку.
Вот пример кода (я его не запускал):
@SupportedAnnotationTypes("*") // needed to run on all classes being compiled
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class DefaultConstructor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
for (TypeElement type : ElementFilter.typesIn(roundEnv.getRootElements())) {
if (requiresDefaultConstructor(type))
checkForDefaultConstructor(type);
}
return false;
}
private void checkForDefaultConstructor(TypeElement type) {
for (ExecutableElement cons :
ElementFilter.constructorsIn(type.getEnclosedElements())) {
if (cons.getParameters().isEmpty())
return;
}
// Couldn't find any default constructor here
processingEnv.getMessager().printMessage(
Diagnostic.Kind.ERROR, "type is missing a default constructor",
type);
}
private boolean requiresDefaultConstructor(TypeElement type) {
// sample: require any JPA Entity to have a default constructor
return type.getAnnotation(Entity.class)) != null
|| type.getQualifiedName().toString().contains("POJO");
}
}
Обработчик аннотации становится еще проще, если вы вводите аннотацию (например, RequiresDefaultAnnotation).
Объявление требования наличия квалификатора по умолчанию
:: Я также предполагаю, что OP запрашивает механизм, предотвращающий случайные ошибки для разработчиков, особенно написанный кем-то другим.::
Должен быть механизм объявления классов, для которых требуется процессор по умолчанию. Надеюсь, у вас уже есть критерии для этого, будь то шаблон в имени, шаблон в квалификаторе, возможная аннотация и/или базовый тип. В приведенном выше примере, вы можете указать критерии в методе requiresDefaultConstructor()
. Вот пример того, как это можно сделать:
-
На основе шаблона имени.
TypeElement
предоставляют доступ к полному имени и имени пакета.return type.getQualifiedName().toString().contains("POJO");
-
На основе аннотации, содержащейся в объявлении типа. Например, все классы Java Bean Entity должны иметь конструкторы не по умолчанию
return type.getAnnotation(Entity.class) != null;
-
На основе абстрактного класса или интерфейса.
TypeElement basetype = processingEnv.getElements().getTypeElement("com.notnoop.mybase"); return processingEnv.getTypes().isSubtype(type.asType(), basetype.asType());
-
[Рекомендуемый подход]: Если вы используете интерфейс базового типа, я рекомендую смешивать подход аннотации с интерфейсом базового типа. Вы можете объявить аннотацию, например.
MyPlain
, вместе с мета-аннотацией:@Inherited
. Затем вы можете аннотировать базовый тип с помощью этой аннотации, тогда все подклассы также наследуют аннотацию. Тогда ваш метод будетreturn type.getAnnotation(MyPlain.class) != null;
Это лучше, потому что это немного более настраиваемо, если шаблон действительно основан на иерархии типов, и у вас есть корневой класс.
Как упоминалось ранее, только потому, что он называется "обработкой аннотации", это означает, что вы должны использовать аннотации! Какой подход в списке, который вы хотите использовать, зависит от вашего контекста. В основном, дело в том, что любую логику, которую вы хотели бы настроить в своих инструментах обеспечения развертывания, эта логика идет в requiresDefaultConstructor
.
Классы процессора будут работать на
Вызов обработчиков аннотаций в любом классе зависит от SupportedAnnotationTypes
. Если мета-аннотация SupportedAnnotationTypes
задает конкретную аннотацию, то процессор будет работать только на тех классах, которые содержат такую аннотацию.
Если SupportedAnnotationTypes
равно "*"
, тогда процессор будет вызываться во всех классах, аннотированных или нет! Проверьте [Javadoc] (http://java.sun.com/javase/6/docs/api/javax/annotation/processing/Processor.html#getSupportedAnnotationTypes()), в котором говорится:
Наконец,
"*"
сам по себе представляет набор всех типов аннотаций, включая пустое множество. Обратите внимание, что процессор не должен требовать"*"
, если это не фактически обрабатывать все файлы; утверждение ненужных аннотаций может в некоторых случаях сред.
Обратите внимание, как возвращается false
, чтобы гарантировать, что процессор не требует всех аннотаций.