Новые возможности Spring 6 и Spring Boot 3 — AOT, который вы должны знать, настолько прост
Новые возможности Spring 6 и Spring Boot 3 — AOT, который вы должны знать, настолько прост

Новые возможности Spring 6.0

1. История развития Spring

2. АОТ

AOT — это новая функция, представленная в Spring 6.0, компиляции Ahead of Time.

1. Обзор АОТ

1.1 Связь между JIT и AOT

1.1.1 JIT

JIT (Just-in-time) динамическая компиляция, JIT-компиляция, то есть компиляция во время работы, то есть, когда программа работает, код генерируется динамически. Запуск происходит относительно медленно, и для компиляции требуются ресурсы времени выполнения. .

1.1.2 AOT

AOT, Ahead Of Time, относится к компиляции перед запуском. Предварительная компиляция AOT может напрямую преобразовывать исходный код в машинный код, имеет низкое использование памяти и высокую скорость запуска. Она может работать без среды выполнения и напрямую статически связывать среду выполнения с конечной программой. . , но при этом нет никакого повышения производительности во время выполнения, и дальнейшая оптимизация не может быть выполнена в зависимости от условий выполнения программы. Недостаток AOT заключается в том, что компиляция перед запуском программы увеличивает время установки программы.

Проще говоря:JITнемедленныйкомпилироватьэто во время работы программы,Преобразование байт-кода в машинный код, который может выполняться непосредственно на оборудовании.,AOT-компиляция — это процесс преобразования байт-кода в машинный код перед запуском программы.

3. Грааль ВМ

GraalVM поддерживает как AOT, так и JIT. Поддерживает несколько языков разработки.

  Технология AOT, поддерживаемая Spring6, эта GraalVM является базовой поддержкой, а Spring также обеспечивает первоклассную поддержку собственных образов GraalVM. GraalVM — это высокопроизводительный JDK, предназначенный для ускорения выполнения приложений, написанных на Java и других языках JVM, а также обеспечивающий среду выполнения для JavaScript, Python и многих других популярных языков. GraalVM предлагает два способа запуска Java-приложений: с помощью JIT-компилятора Graal на JVM HotSpot или в виде заранее скомпилированного собственного исполняемого файла (AOT). Многоязычные возможности GraalVM позволяют смешивать несколько языков программирования в одном приложении, устраняя при этом затраты на вызовы на иностранных языках. GraalVM добавляет усовершенствованный JIT-оптимизирующий компилятор, написанный на Java, в виртуальную машину Java HotSpot.

GraalVM имеет следующие возможности:

(1) Усовершенствованный оптимизирующий компилятор, генерирующий более быстрый и компактный код, требующий меньше вычислительных ресурсов.

(2) Компиляция собственного образа AOT заранее компилирует приложения Java в собственные двоичные файлы, запускается немедленно и достигает максимальной производительности без предварительного нагрева.

(3) Полиглотное программирование использует лучшие функции и библиотеки популярных языков в одном приложении без дополнительных затрат.

(4) Расширенные инструменты для отладки, мониторинга, анализа и оптимизации потребления ресурсов на Java и нескольких языках.

1. Установка GraalVM

1.1 Скачать GraalVM

Адрес загрузки: https://www.graalvm.org/downloads/

Просто загрузите версию сообщества, нажмите, чтобы войти, и выберите соответствующую версию: https://github.com/graalvm/graalvm-ce-builds/releases.

После скачивания разархивируйте его

1.2 Настройка переменных среды

Добавлено: GRAALVM_HOME.

Редактировать пользовательские переменные

Измените JAVA_HOME на местоположение graalvm.

Проверьте, прошла ли настройка успешно

1.3 Установка плагина собственного образа

Используйте команду gu install Native-image, чтобы загрузить и установить плагин, поскольку версия сообщества не обеспечивает поддержку по умолчанию. Нужно скачать вручную

1.4 Native Image

 Native image (локальный образ) — технология создания нативных приложений на платформе Java. Он компилирует приложения Java в собственный машинный код для запуска без необходимости использования виртуальной машины Java (JVM). Это позволяет приложениям запускаться быстрее, работать более эффективно и использовать меньше памяти.

Native image использует технологию компилятора GraalVM для преобразования приложений Java в локальные исполняемые файлы, поддерживая несколько платформ операционных систем, таких как Windows, Linux и MacOS. Кроме того, образ Native может упаковывать приложения Java в один исполняемый файл для упрощения развертывания и распространения.

 Используя собственный образ, разработчики могут создавать и развертывать приложения Java как собственные приложения, что приводит к повышению производительности и удобству взаимодействия с пользователем.

2. Установите среду компиляции C++.

2.1 Загрузите Visual Studio

https://visualstudio.microsoft.com/zh-hans/downloads/

Аналогично мы можем скачать версию сообщества

2.2 Установите Visual Studio

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

Ожидание онлайн-загрузки

Обратите внимание на варианты установки и продолжайте ждать.

Создайте обычный файл Hello.java.

Язык кода:javascript
копировать
public class Hello{

	public static void main(String[] args){
		System.out.println("Hello World ...");
	}
}

Затем скомпилируйте его через javac Hello.java.

Выполняется через собственный образ Hello

Файл Hello.exe создается с помощью Native-Image, и мы можем создать его напрямую.

4. Настоящий бой SpringBoot

  Мы также можем заранее скомпилировать наш проект через AOT в проекте SpringBoot и создать новый Maven-проект. Затем добавьте соответствующие зависимости

Язык кода:javascript
копировать
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.2</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

В то же время нам также необходимо добавить соответствующий плагин SpringBoot.

Язык кода:javascript
копировать
    <build>
        <plugins>
            <plugin>
                <groupId>org.graalvm.buildtools</groupId>
                <artifactId>native-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

Затем мы можем написать простой тест кода

Затем мы открываем командную строку x64 Native Tools для VS 2019. Затем нам нужно переключиться в каталог проекта

Затем выполните mvn -Pnative own:compile для компиляции. Если компиляция прошла успешно, в целевом каталоге будет создан EXE-файл. Просто запустите файл позже

Скомпилировано успешно

Затем дважды щелкните, чтобы выполнить exe-файл. Вы обнаружите, что это будет намного быстрее

5. Подсказки во время выполнения

 Запуск приложения в качестве собственного образа требует дополнительной информации по сравнению с обычной средой выполнения JVM. Например, GraalVM необходимо заранее знать, использует ли компонент отражение. Аналогично, ресурсы пути к классам не предоставляются в собственном образе, если это не указано явно. Поэтому, если приложению необходимо загрузить ресурс, оно должно ссылаться на него из соответствующего файла конфигурации собственного образа GraalVM.

APIRuntimeHintsСобирать во время выполненияотражение、Загрузка ресурсов、Сериализация и JDK Нужен агент.

1. Анализ случая

Объявить общий тип сущности

Язык кода:javascript
копировать
public class UserEntity {
    public String hello(){
        return "hello ...";
    }
}

Дальше оперируем и обрабатываем через отражение в контроллере

Язык кода:javascript
копировать
    @GetMapping("/hello")
    public String hello(){
        String res = "hello";
        try {
            Method hello = UserEntity.class.getMethod("hello");
            res =  (String)hello.invoke(UserEntity.class.newInstance(),null);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        }
        return res;
    }

Затем скомпилируйте его в exe-файл с помощью команды

После запуска exe-файла. Инициируем запрос через браузер

В HelloController. Мы используем конструктор UserEntity без параметров посредством отражения. Если ничего не будет сделано. Тогда его нельзя будет выполнить после того, как он будет преобразован в двоичный исполняемый файл. Выше приведено конкретное сообщение об ошибке. для этой ситуации. Мы можем справиться с этим с помощью механизма Runtime Hints.

2. RuntimeHintsRegistrar

Решения предоставлены официальным сайтом. Мы настраиваем класс реализации интерфейса RuntimeHintsRegistrar, а затем внедряем класс реализации в Spring.

наша собственная реализация

Язык кода:javascript
копировать
@RestController
@ImportRuntimeHints(HelloController.UserEntityRuntimeHints.class)
public class HelloController {

    @GetMapping("/hello")
    public String hello(){
        String res = "hello";
        try {
            Method hello = UserEntity.class.getMethod("hello");
            res =  (String)hello.invoke(UserEntity.class.newInstance(),null);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        }
        return res;
    }

    static class UserEntityRuntimeHints implements RuntimeHintsRegistrar{

        @Override
        public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
            try {
                hints.reflection().registerConstructor(UserEntity.class.getConstructor(), ExecutableMode.INVOKE);
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

6. Основной код SpringBoot

SpringApplicationAotProcessor

  мы выполняем mvn -Pnative native:compileвремя встречиосуществлятьGraalVMСоответствующие инструкции в。в конце концов позвонюSpringApplicationAotProcessorвmain Метод для выполнения связанных операций предварительной компиляции.

Язык кода:javascript
копировать
	public static void main(String[] args) throws Exception {
		int requiredArgs = 6; // Вызов основного метода получает 6 параметров
		Assert.isTrue(args.length >= requiredArgs, () -> "Usage: " + SpringApplicationAotProcessor.class.getName()
				+ " <applicationName> <sourceOutput> <resourceOutput> <classOutput> <groupId> <artifactId> <originalArgs...>");
		// Получите начальный класс проекта SpringBoot.
		Class<?> application = Class.forName(args[0]);
		// Передаваемые параметры завершают настройку соответствующего сгенерированного каталога.
		Settings settings = Settings.builder().sourceOutput(Paths.get(args[1])).resourceOutput(Paths.get(args[2]))
				.classOutput(Paths.get(args[3])).groupId((StringUtils.hasText(args[4])) ? args[4] : "unspecified")
				.artifactId(args[5]).build();
		String[] applicationArgs = (args.length > requiredArgs) ? Arrays.copyOfRange(args, requiredArgs, args.length)
				: new String[0];
	  // осуществлять process метод
		new SpringApplicationAotProcessor(application, settings, applicationArgs).process();
	}

Введите метод обработки

Язык кода:javascript
копировать
	public final T process() {
		try {
			// Установить статус
			System.setProperty(AOT_PROCESSING, "true");
			return doProcess(); // Обработка Coreметод
		}
		finally {
			System.clearProperty(AOT_PROCESSING);
		}
	}

Введите метод doProcess().

Язык кода:javascript
копировать
 	@Override
	protected ClassName doProcess() {
		deleteExistingOutput(); // Удалить существующий каталог
		// Запустите службу SpringBoot  Но он не будет сканировать бобы
		GenericApplicationContext applicationContext = prepareApplicationContext(getApplicationClass());
		return performAotProcessing(applicationContext);
	}

подготовка ApplicationContext:

Язык кода:javascript
копировать
	@Override
	protected GenericApplicationContext prepareApplicationContext(Class<?> application) {
		return new AotProcessorHook(application).run(() -> {
			Method mainMethod = application.getMethod("main", String[].class);
			return ReflectionUtils.invokeMethod(mainMethod, null, new Object[] { this.applicationArgs });
		});
	}

На этот раз для запуска SpringBoot будет выполнен основной метод класса запуска.

При создании объекта контекста Spring во время запуска будет выполнена следующая обработка:

Язык кода:javascript
копировать
	private ConfigurableApplicationContext createContext() {
		if (!AotDetector.useGeneratedArtifacts()) {
			return new AnnotationConfigServletWebServerApplicationContext();
		}
		return new ServletWebServerApplicationContext();
	}

Если AOT не используется, будет создан AnnotationConfigServletWebServerApplicationContext и к нему будет добавлен ConfigurationClassPostProcessor, чтобы класс конфигурации был проанализирован и просканирован. Если AOT используется, будет создан ServletWebServerApplicationContext. Это пустой контейнер и нет ConfigurationClassPostProcessor. в нем, поэтому сканирование не будет запускаться в будущем.

Вернитесь к методу PerformAotProcessing.

Язык кода:javascript
копировать
	protected ClassName performAotProcessing(GenericApplicationContext applicationContext) {
		FileSystemGeneratedFiles generatedFiles = createFileSystemGeneratedFiles();
		DefaultGenerationContext generationContext = new DefaultGenerationContext(
				createClassNameGenerator(), generatedFiles);
		ApplicationContextAotGenerator generator = new ApplicationContextAotGenerator();
		// Выполнение связанных операций сканирования
		ClassName generatedInitializerClassName = generator.processAheadOfTime(applicationContext, generationContext);
		//Если есть регистрационная информация для отражения. Здесь соответствующая информация будет сгенерирована в RuntimeHints, соответствующем отражению-config.json.
		registerEntryPointHint(generationContext, generatedInitializerClassName);
		// Создать Java-документ в исходном каталоге.
		generationContext.writeGeneratedContent();
		//  Запишите содержимое RuntimeHints в различные конфигурации Graalvm в документе каталога ресурсов.
		writeHints(generationContext.getRuntimeHints());
		writeNativeImageProperties(getDefaultNativeImageArguments(getApplicationClass().getName()));
		return generatedInitializerClassName;
	}

Логика в процессеAheadOfTime

Язык кода:javascript
копировать
	public ClassName processAheadOfTime(GenericApplicationContext applicationContext,
			GenerationContext generationContext) {
		return withCglibClassHandler(new CglibClassHandler(generationContext), () -> {
			// Обработка сканирования
			applicationContext.refreshForAotProcessing(generationContext.getRuntimeHints());
		// Получить объект Bean Factory
		DefaultListableBeanFactory beanFactory = applicationContext.getDefaultListableBeanFactory();
			ApplicationContextInitializationCodeGenerator codeGenerator =
					new ApplicationContextInitializationCodeGenerator(generationContext);
			new BeanFactoryInitializationAotContributions(beanFactory).applyTo(generationContext, codeGenerator);
			return codeGenerator.getGeneratedClass().getName();
		});
	}

Введите метод обновленияForAotProcessing.

Язык кода:javascript
копировать
	public void refreshForAotProcessing(RuntimeHints runtimeHints) {
		if (logger.isDebugEnabled()) {
			logger.debug("Preparing bean factory for AOT processing");
		}
		prepareRefresh();
		obtainFreshBeanFactory(); // Получить заводской объект. и завершите операцию сканирования
		prepareBeanFactory(this.beanFactory);
		postProcessBeanFactory(this.beanFactory);
		invokeBeanFactoryPostProcessors(this.beanFactory); // заводской постпроцессор
		this.beanFactory.freezeConfiguration();
		PostProcessorRegistrationDelegate.invokeMergedBeanDefinitionPostProcessors(this.beanFactory);
		preDetermineBeanTypes(runtimeHints);
	}

Логика метода BeanFactoryInitializationAotContributions: он считывает загрузчик файла aot.properties и инкапсулирует BeanFactory в объект Loader, а затем передает его в

Язык кода:javascript
копировать
	BeanFactoryInitializationAotContributions(DefaultListableBeanFactory beanFactory) {
		this(beanFactory, AotServices.factoriesAndBeans(beanFactory));
	}
boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose