Ломбок часто используется, но знаете ли вы, как это работает?

Java

Я считаю, что все использовали Lombok в проекте, потому что он может упростить наш код, но функций не так много. Так что же такое ломбок?Ломбок — это инструмент, который может помочь нам упростить и исключить некоторый обязательный, но раздутый Java-код в виде простых аннотаций.Проще говоря, например, мы создаем новый класс, а затем пишем в нем A несколько полей, а затем обычно нам нужно вручную создавать методы получения и установки, конструкторы и т. д. Роль ломбока состоит в том, чтобы избавить нас от необходимости вручную создавать эти коды, его можно использовать при компиляции исходного кода.Автоматическое создание этих методы для нас.

Так как же именно Ломбок это делает? Фактически, нижний слой должен использовать функцию аннотации времени компиляции.

Как использовать Ломбок

Lombok — это проект с открытым исходным кодом, код находится вlombok, если это проект Gradle, на него можно напрямую ссылаться в проекте следующим образом.

1compile ("org.projectlombok:lombok:1.16.6")

Функции

Так что же делает Ломбок? На самом деле это очень просто, один из самых простых примеров — автоматически генерировать некоторые методы, добавляя аннотации, чтобы сделать наш код более лаконичным и понятным. Например, следующий класс.

 1@Data
2public class TestLombok {
3    private String name;
4    private Integer age;
5
6    public static void main(String[] args) {
7        TestLombok testLombok = new TestLombok();
8        testLombok.setAge(12);
9        testLombok.setName("zs");
10    }
11}

Мы используем ЛомбокDataАннотация, без записиget、setметод можно использовать и тогда, когдаget、setметод. Посмотрим, как он скомпилированclassфайл, вы можете видеть, что он был автоматически сгенерирован для насget、setметод.

 1public class TestLombok {
2    private String name;
3    private Integer age;
4
5    public static void main(String[] args) {
6        TestLombok testLombok = new TestLombok();
7        testLombok.setAge(12);
8        testLombok.setName("zs");
9    }
10
11    public TestLombok() {
12    }
13
14    public String getName() {
15        return this.name;
16    }
17
18    public Integer getAge() {
19        return this.age;
20    }
21
22    public void setName(String name) {
23        this.name = name;
24    }
25
26    public void setAge(Integer age) {
27        this.age = age;
28    }
29
30}

Конечно, функций Lombok больше, чем это, и есть много других аннотаций, которые помогут нам легко разрабатывать.В Интернете есть много способов использовать Lombok, поэтому я не буду повторяться здесь. В обычных условиях мы настраиваем аннотации в проекте или используемSpringв рамке@Controller、@Serviceи т.д. Эти аннотации运行时注解, аннотации времени выполнения в основном реализуются посредством отражения. иLombokреализуется с использованием аннотаций времени компиляции. Так что же такое аннотации времени компиляции?

аннотации времени компиляции

Аннотации (также известные как метаданные) предоставляют нам формальный способ добавления информации в наш код, благодаря чему нам очень удобно использовать эти данные в более поздний момент времени. —————— Отрывок из книги «Мышление на Java»

Аннотации в Java делятся нааннотации времени выполненияианнотации времени компиляцииАннотации времени выполнения — это информация, которую мы часто используем для получения наших аннотаций посредством отражения во время работы программы, а затем для выполнения некоторых операций. И что такое аннотации времени компиляции? Он обрабатывается процессором аннотаций во время компиляции программы.

  • Время компиляции. Время компиляции языка Java является неопределенной операцией, поскольку оно может.java`文件转化成`.classПроцесс файла; он также может относиться к процессу преобразования байт-кода в машинный код; он также может напрямую относиться к*.javaПроцесс компиляции в собственный машинный код
  • Время выполнения: процесс от загрузки файлов байт-кода JVM в память до выгрузки после окончательного использования относится к области времени выполнения.

Инструмент обработки аннотаций

Инструмент обработки аннотаций apt (Инструмент обработки аннотаций), который представляет собой инструмент, предоставляемый Sun для облегчения процесса обработки аннотаций, apt предназначен для управления исходными файлами Java, а не скомпилированными классами.

Это инструмент javac, что в переводе с китайского означает процессор аннотаций времени компиляции. APT можно использовать для сканирования и обработки аннотаций во время компиляции. Информацию об аннотациях и аннотируемых объектах можно получить через APT, после получения которой мы можем автоматически генерировать некоторые коды в соответствии с требованиями, устраняя необходимость ручного написания. Обратите внимание, что получение аннотаций и генерация кода находятся в коде.компилироватьПо завершении это значительно повышает производительность программы по сравнению с аннотациями, обрабатывающими отражение во время выполнения. Ядром APT является класс AbstractProcessor.

В обычных условиях с помощью инструмента APT можно создать только некоторые файлы (Не только файл класса, который мы себе представляем, но и файл xml и так далее.) и не может изменять исходную информацию о файле.

Но тут могут быть сомнения,LombokРазве это не просто добавление некоторой информации к нашему исходному файлу? Я объясню подробно позже, вот краткое введение, на самом делеLombokизменено в Javaабстрактное синтаксическое деревоASTТолько после этого он модифицировал информацию своего исходного класса.

Далее мы покажем, как использоватьAPTИнструмент создает файл класса, а затем мы говоримLombokКак изменить свойства в существующем классе.

определить аннотации

Прежде всего, конечно, нам нужно определить наши собственные аннотации.

1@Retention(RetentionPolicy.SOURCE) // 注解只在源码中保留
2@Target(ElementType.TYPE) // 用于修饰类
3public @interface GeneratePrint {
4
5    String value();
6}

RetentionВ аннотации есть значение атрибута, котороеRetentionPolicyкласс перечисления типа,RetentionPolicyВ классе enum есть три значения.

1public enum RetentionPolicy {
2
3    SOURCE,
4
5    CLASS,
6
7    RUNTIME
8}
  • SOURCEМодифицированная аннотация: Модифицированная аннотация, указывающая, что информация аннотации будет отброшена компилятором и не останется в файле класса, а информация аннотации останется только в исходном файле.
  • CLASSУкрашенные аннотации: информация, указывающая на аннотации, сохраняется в файле класса (файле байт-кода) при компиляции программы, но не считывается виртуальной машиной во время выполнения.
  • RUNTIMEУкрашенные аннотации: информация, указывающая на аннотации, сохраняется в файле класса (файле байт-кода) при компиляции программы и будет сохранена виртуальной машиной во время выполнения.Таким образом, его можно вызывать через отражение, поэтому аннотации используют этот параметр в обычном режиме выполнения.

TargetВ аннотации также есть значение атрибута, котороеElementTypeПеречень типов. Он используется для изменения места использования этой аннотации.

 1public enum ElementType {
2    TYPE,
3
4    FIELD,
5
6    METHOD,
7
8    PARAMETER,
9
10    CONSTRUCTOR,
11
12    LOCAL_VARIABLE,
13
14    ANNOTATION_TYPE,
15
16    PACKAGE,
17
18    TYPE_PARAMETER,
19
20    TYPE_USE
21}

Определение процессоров аннотаций

Если мы хотим определить процессор аннотаций, нам нужно наследоватьAbstractProcessorсвоего рода. После наследования основные типы кадров следующие:

 1@SupportedSourceVersion(SourceVersion.RELEASE_8)
2@SupportedAnnotationTypes("aboutjava.annotion.MyGetter")
3public class MyGetterProcessor extends AbstractProcessor {
4    @Override
5    public synchronized void init(ProcessingEnvironment processingEnv) {
6    super.init(processingEnv);
7    }
8
9    @Override
10    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
11        return true;
12    }
13}

Мы видим, что в подклассе есть две аннотации выше, аннотации описываются следующим образом

  • @SupportedSourceVersion: указывает поддерживаемую версию Java.
  • @SupportedAnnotationTypes: указывает аннотацию, которую должен обрабатывать этот процессор.

Унаследовал два метода родительского класса, методы описываются следующим образом

  • метод init: в основном для получения некоторой информации об окружающей среде во время компиляции
  • метод процесса: во время компиляции метод, выполняемый компилятором. Здесь мы пишем конкретную логику

Мы демонстрируем, как использовать наследованиеAbstractProcessorclass для генерации классов во время компиляции, поэтому мы находимся вprocessметод для написания кода для нашего сгенерированного класса. Следующее.

 1@Override
2public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
3    StringBuilder builder = new StringBuilder()
4            .append("package aboutjava.annotion;\n\n")
5            .append("public class GeneratedClass {\n\n") // open class
6            .append("\tpublic String getMessage() {\n") // open method
7            .append("\t\treturn \"");
8    // for each javax.lang.model.element.Element annotated with the CustomAnnotation
9    for (Element element : roundEnv.getElementsAnnotatedWith(MyGetter.class)) {
10        String objectType = element.getSimpleName().toString();
11        // this is appending to the return statement
12        builder.append(objectType).append(" says hello!\\n");
13    }
14    builder.append("\";\n") // end return
15            .append("\t}\n") // close method
16            .append("}\n"); // close class
17    try { // write the file
18        JavaFileObject source = processingEnv.getFiler().createSourceFile("aboutjava.annotion.GeneratedClass");
19        Writer writer = source.openWriter();
20        writer.write(builder.toString());
21        writer.flush();
22        writer.close();
23    } catch (IOException e) {
24        // Note: calling e.printStackTrace() will print IO errors
25        // that occur from the file already existing after its first run, this is normal
26    }
27    return true;
28}

Определение классов с помощью аннотаций (тестовые классы)

Вышеупомянутые два класса являются основными классами инструментов, один определяет аннотации, другой определяет процессоры аннотаций, а затем мы определяем тестовый класс (TestAno.java). Мы добавляем наш пользовательский класс аннотаций в класс.

1@MyGetter
2public class TestAno {
3
4    public static void main(String[] args) {
5        System.out.printf("1");
6    }
7}

Таким образом, мы можем генерировать файлы во время компиляции. Далее мы продемонстрируем генерацию файлов во время компиляции. Не беспокойтесь о прямой компиляции javac сейчас.MyGetterКлассы — это классы аннотаций, да, ноMyGetterProcessorявляется обработчиком класса аннотаций, то мы компилируемTestAnoОбработчик запускается при создании файла Java. Таким образом, два класса не могут быть скомпилированы вместе.

Позвольте мне сначала показать вам мою структуру каталогов

1aboutjava
2    -- annotion
3        -- MyGetter.java
4        -- MyGetterProcessor.java
5        -- TestAno.java

Итак, мы сначала компилируем класс аннотаций и класс процессора аннотаций.

1javac aboutjava/annotion/MyGett*

Далее компилируем наш тестовый класс.На этот раз нам нужно добавить его при компиляцииprocessorПараметр для указания соответствующего класса обработки аннотаций.

1javac -processor aboutjava.annotion.MyGetterProcessor aboutjava/annotion/TestAno.java

Как видно на динамическом графике, файл Java генерируется автоматически.

кодовый адрес

Суммировать

В этой статье будет вторая статья, объясняющая принцип Lombok и способы изменения содержимого исходного класса. В качестве предварительного знания эта статья кратко представляет, что такое процессор аннотаций и как использовать процессор аннотаций для выполнения действий, которые мы можем выполнять только во время компиляции. Надеюсь, вы сможете протестировать его на своей машине.Если у вас есть какие-либо вопросы по этой статье, пожалуйста, укажите.

Если вам интересно, можете обратить внимание на мой новый паблик аккаунт и поискать [Сумка с сокровищами программиста]. Или просто отсканируйте код ниже.

Ссылаться на