Для этого вы можете создать процессор аннотаций. Процессоры аннотаций - это плагины компилятора, которые запускаются во время компиляции. Их ошибки отображаются как ошибки компилятора и могут даже остановить сборку.
Вот пример кода (хотя я его не запускал):
@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");
}
}
Процессор аннотаций становится еще проще, если вы вводите аннотацию (например, требует аннотацию по умолчанию).
Заявление о необходимости иметь квалификатор по умолчанию
:: Я также предполагаю, что ОП запрашивает механизм, который предотвращает случайные ошибки для разработчиков, особенно написанные кем-то другим.
Должен существовать механизм для объявления того, для каких классов требуется процессор по умолчанию. Надеюсь, у вас уже есть критерии для этого, будь то шаблон в имени, шаблон в классификаторе, возможная аннотация и / или базовый тип. В приведенном выше примере вы можете указать критерии в методе 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
, чтобы процессор не запрашивал все аннотации.