Spring Boot: автоматическая настройка четырех артефактов
Spring Boot: автоматическая настройка четырех артефактов

Введение

Spring Boot очень прост и удобен в использовании. Он скрывает много контента, и вам не нужно об этом заботиться. Но хорошему разработчику может быть интересно узнать, что именно происходит за автоматической настройкой Spring Boot?

Spring Boot не является новой технологией, но стартер Spring Boot помогает нам настроить несколько bean-компонентов, управляемых Spring. Когда наш проект зависит от этих jar-файлов и запускает приложение Spring, в контейнере Spring уже есть объекты в пакете, которые создаются и управляются.

Короче говоря, автоконфигурация Spring Boot представляет собой способ автоматической настройки приложения Spring на основе зависимостей, присутствующих в пути к классам. Вы также можете по определению исключить определенные bean-компоненты, содержащиеся в классах автоконфигурации. Это может сделать разработку быстрее и проще.

Суть автоматической настройки Springboot заключается в автоматической настройке различных компонентов Spring. Затем приложение может использовать компонент напрямую с помощью методов внедрения, таких как @Autowired. Например, автоматически настройте такие компоненты, как redisTemplate и jdbcTemplate.

1. Создайте приложение Spring Boot через класс запуска.

Создать приложение Spring Boot очень просто: просто создайте стартовый класс, содержащий main.

Язык кода:javascript
копировать
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class App
{
    public static void main(String[] args)
    {
        ApplicationContext ctx = SpringApplication.run(App.class, args);
    }
}

Вышеупомянутый класс называется классом запуска приложения Spring Boot. Он направляет и запускает приложение Spring с помощью метода Java main(). Обычно он содержит следующее содержимое:

  • Создайте экземпляр Spring ApplicationContext.
  • Получите параметры командной строки и преобразуйте их в свойства Spring.
  • в соответствии с Конфигурациязагрузить всеSpring Бобы. Другие операции могут выполняться в зависимости от потребностей проекта.

2. Аннотация @SpringBootApplication

Эта аннотация на самом деле представляет собой ярлык с тремя примененными аннотациями.

2.1 @SpringBootConfiguration

@SpringBootConfiguration — это новая аннотация, появившаяся в Spring Boot2. Ранее мы использовали аннотацию @Configuration. Вы можете заменить ее на @Configuration. Оба они выполняют одну и ту же функцию. Это указывает на то, что класс является классом конфигурации и его следует сканировать на предмет дальнейшей конфигурации и определений компонентов.

2.2 @EnableAutoConfiguration

Эта аннотация используется для включения автоматической настройки контекста приложения Spring, пытаясь угадать и настроить bean-компоненты, которые могут вам понадобиться. Классы автоконфигурации обычно применяются на основе вашего пути к классам и определяемых вами bean-компонентов. Автоматическая конфигурация пытается быть максимально умной и отступает по мере того, как вы определяете больше своей собственной конфигурации. Вы всегда можете вручную исключить любую конфигурацию, которую вы не хотите применять, двумя способами:

Используйте исключение Имя() Используйте свойство Spring.autoconfigure.exclude в файле свойств.

2.3 @ComponentScan

Эта аннотация обеспечивает поддержку параллельно с элементом Spring XML context:comComponent-scan. Либо basePackageClasses(), либо basePackages() могут определять конкретные пакеты для сканирования. Если конкретный пакет не определен, будет проверен пакет того класса, в котором объявлена ​​эта аннотация.

3. Индивидуальная автоматическая конфигурация.

Чтобы создать пользовательскую автоконфигурацию, нам нужно создать класс, аннотированный @Configuration, и зарегистрировать его. Давайте создадим собственную конфигурацию для источника данных MySQL:

Язык кода:javascript
копировать
@Configuration
public class MySQLAutoconfiguration {
  //...
}

Следующим необходимым шагом является регистрация класса в качестве кандидата на автоконфигурацию, добавив его имя в свойство org.springframework.boot.autoconfigure.EnableAutoConfiguration в стандартном файле resources/META-INF/spring.factories:

Язык кода:javascript
копировать
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.peterwanghao.samples.springboot.autoconfiguration.MySQLAutoconfiguration

Если мы хотим, чтобы наш класс автоконфигурации имел приоритет над другими кандидатами автоконфигурации, мы можем добавить аннотацию @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE). Автоконфигурация разработана с использованием классов и компонентов, отмеченных аннотацией @Conditional, чтобы можно было заменить автоконфигурацию или определенные ее части. Обратите внимание, что автоконфигурация работает только в том случае, если в приложении не определены автоконфигурируемые bean-компоненты. Если вы определяете компонент, значение по умолчанию будет переопределено.

3.1 Условные аннотации на основе классов

Условия класса позволяют нам указывать классы, указанные с помощью аннотации @ConditionalOnClass, или использовать аннотацию @ConditionalOnMissingClass для указания классов, которые не существуют в пути к классам. Укажем, что MySQLConfiguration будет загружаться только в том случае, если присутствует класс DataSource, и в этом случае можно предположить, что приложение будет использовать базу данных:

Язык кода:javascript
копировать
@Configuration
@ConditionalOnClass(DataSource.class)
public class MySQLAutoconfiguration {
    //...
}
3.2 Условные аннотации на основе компонентов

Если мы хотим включить компонент только в том случае, если указанный компонент существует, мы можем использовать аннотации @ConditionalOnBean и @ConditionalOnMissingBean. В качестве примера давайте добавим bean-компонентentityManagerFactory в наш класс конфигурации и укажем, что если bean-компонент с именем dataSource существует, а bean-компонент с именемentityManagerFactory еще не определен, мы создаем этот bean-компонент:

Язык кода:javascript
копировать
 @Bean
 @ConditionalOnBean(name = "dataSource")
 @ConditionalOnMissingBean

 public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
  final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
  em.setDataSource(dataSource());
  em.setPackagesToScan("com.peterwanghao.samples.springboot.autoconfiguration.example");
  em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
  if (additionalProperties() != null) {
   em.setJpaProperties(additionalProperties());
  }
  return em;
 }

Давайте настроим bean-компонент transactionManager, который будет загружаться только в том случае, если еще не определен bean-компонент типа JpaTransactionManager:

Язык кода:javascript
копировать
@Bean
 @ConditionalOnMissingBean(type = "JpaTransactionManager")
 JpaTransactionManager transactionManager(final EntityManagerFactory entityManagerFactory) {
  final JpaTransactionManager transactionManager = new JpaTransactionManager();
  transactionManager.setEntityManagerFactory(entityManagerFactory);
  return transactionManager;
 }
3.3 Условные аннотации на основе атрибутов

Аннотация @ConditionalOnProperty используется для указания, будет ли загружаться конфигурация в зависимости от наличия и значения свойства среды Spring. Сначала давайте добавим в конфигурацию исходный файл свойств, чтобы определить, откуда читать свойства:

Язык кода:javascript
копировать
@PropertySource("classpath:mysql.properties")
public class MySQLAutoconfiguration {
    //...
}

Мы можем настроить основной компонент DataSource, который будет использоваться для создания соединения с базой данных и будет загружаться только в том случае, если присутствует свойство с именем usemysql. Мы можем использовать свойство hasValue для указания определенных значений свойств usemysql, которые должны совпадать. Если для атрибута usemysql установлено значение local, давайте определим bean-компонент dataSource со значением по умолчанию, который подключается к локальной базе данных с именем myDb:

Язык кода:javascript
копировать
@Bean
 @ConditionalOnProperty(name = "usemysql", havingValue = "local")
 @ConditionalOnMissingBean
 public DataSource dataSource() {
  final DriverManagerDataSource dataSource = new DriverManagerDataSource();
  dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
  dataSource.setUrl("jdbc:mysql://localhost:3306/myDb?createDatabaseIfNotExist=true&&serverTimezone=GMT%2B8");
  dataSource.setUsername("root");
  dataSource.setPassword("123456");
  return dataSource;
 }

Если для атрибута usemysql установлено значение custom, компонент источника данных будет настроен с использованием URL-адреса базы данных, пользователя и пароля значения пользовательского атрибута:

Язык кода:javascript
копировать
@Bean(name = "dataSource")
 @ConditionalOnProperty(name = "usemysql", havingValue = "custom")
 @ConditionalOnMissingBean
 public DataSource dataSource2() {
  final DriverManagerDataSource dataSource = new DriverManagerDataSource();
  dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
  dataSource.setUrl(env.getProperty("mysql.url"));
  dataSource.setUsername(env.getProperty("mysql.user") != null ? env.getProperty("mysql.user") : "");
  dataSource.setPassword(env.getProperty("mysql.pass") != null ? env.getProperty("mysql.pass") : "");
  return dataSource;
 }

Файл mysql.properties будет содержать свойства usemysql:

usemysql=local

Если приложение, использующее MySQLAutoconfiguration, желает переопределить свойства по умолчанию, все, что ему нужно сделать, это добавить разные значения для свойств mysql.url, mysql.user и mysql.pass в файл mysql.properties, а также добавить usemysql. = пользовательская строка.

3.4 Условные аннотации на основе ресурсов

Добавление аннотации @ConditionalOnResource означает, что конфигурация будет загружена только тогда, когда указанный ресурс существует.

Давайте определим метод extraProperties(), который будет возвращать объект Properties, содержащий свойства, специфичные для Hibernate, используемые bean-компонентомentityManagerFactory, только если присутствует файл ресурсов mysql.properties:

Язык кода:javascript
копировать
@ConditionalOnResource(resources = "classpath:mysql.properties")
 @Conditional(HibernateCondition.class)
 final Properties additionalProperties() {
  final Properties hibernateProperties = new Properties();
  hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("mysql-hibernate.hbm2ddl.auto"));
  hibernateProperties.setProperty("hibernate.dialect", env.getProperty("mysql-hibernate.dialect"));
  hibernateProperties.setProperty("hibernate.show_sql",
    env.getProperty("mysql-hibernate.show_sql") != null ? env.getProperty("mysql-hibernate.show_sql")
      : "false");
  return hibernateProperties;
 }

Мы можем добавить специальные свойства Hibernate в файл mysql.properties:

mysql-hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect mysql-hibernate.show_sql=true mysql-hibernate.hbm2ddl.auto=create-drop

3.5 Индивидуальные условия

Если мы не хотим использовать какие-либо доступные условия в Spring Boot, мы также можем определить собственные условия, расширив класс SpringBootCondition и переопределив метод getMatchOutcome().

Давайте создадим условие HibernateCondition для метода extraProperties(), которое будет проверять, присутствует ли класс HibernateEntityManager в пути к классам:

Язык кода:javascript
копировать
static class HibernateCondition extends SpringBootCondition {
  private static final String[] CLASS_NAMES = { "org.hibernate.ejb.HibernateEntityManager",
    "org.hibernate.jpa.HibernateEntityManager" };
  @Override
  public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
   ConditionMessage.Builder message = ConditionMessage.forCondition("Hibernate");
   return Arrays.stream(CLASS_NAMES)
     .filter(className -> ClassUtils.isPresent(className, context.getClassLoader()))
     .map(className -> ConditionOutcome.match(message.found("class").items(Style.NORMAL, className)))
     .findAny().orElseGet(() -> ConditionOutcome.noMatch(
       message.didNotFind("class", "classes").items(Style.NORMAL, Arrays.asList(CLASS_NAMES))));
  }
 }

Затем мы можем добавить условия к методу extraProperties():

Язык кода:javascript
копировать
@Conditional(HibernateCondition.class)
Properties additionalProperties() {
  //...
}
3.6 Условия применения

Мы также можем указать, что конфигурацию можно загружать только внутри/вне веб-контекста, добавив аннотации @ConditionalOnWebApplication или @ConditionalOnNotWebApplication.

4. Проверьте автоматическую конфигурацию.

Давайте создадим очень простой пример для проверки нашей автоматической настройки. Мы будем использовать Spring Data для создания класса сущности с именем MyUser и интерфейса MyUserRepository:

Язык кода:javascript
копировать
@Entity
public class MyUser {
 @Id
 private String email;
 public MyUser() {
 }

 public MyUser(String email) {
  super();
  this.email = email;
 }

 public String getEmail() {
  return email;
 }

 public void setEmail(String email) {
  this.email = email;
 }
}

public interface MyUserRepository extends JpaRepository<MyUser, String> {
}

Чтобы включить автоматическую настройку, мы можем использовать аннотацию @SpringBootApplication или @EnableAutoConfiguration:

Язык кода:javascript
копировать
@SpringBootApplication
public class AutoconfigurationApplication {
 public static void main(String[] args) {
  SpringApplication.run(AutoconfigurationApplication.class, args);
 }
}

Далее давайте напишем тест JUnit, сохраняющий сущность MyUser:

Язык кода:javascript
копировать
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = AutoconfigurationApplication.class)
@EnableJpaRepositories(basePackages = { "com.peterwanghao.samples.springboot.autoconfiguration.example" })
public class AutoconfigurationLiveTest {

    @Autowired
    private MyUserRepository userRepository;

    @Test
    public void whenSaveUser_thenOk() {
        MyUser user = new MyUser("user@email.com");
        userRepository.save(user);
    }
}

5. Отключите классы автоматической настройки.

Если мы хотим исключить автоконфигурацию из загрузки, мы можем добавить аннотацию @EnableAutoConfiguration с атрибутом Exclude или ExcludeName в класс конфигурации:

Язык кода:javascript
копировать
@Configuration
@EnableAutoConfiguration(exclude={MySQLAutoconfiguration.class})
public class AutoconfigurationApplication {
    //...
}

Другой способ отключить определенную автоконфигурацию — установить свойство Spring.autoconfigure.exclude:

spring.autoconfigure.exclude=com.peterwanghao.samples.springboot.autoconfiguration.MySQLAutoconfiguration

6. Заключение

В этом руководстве мы рассказали, как Spring Boot автоматически загружает классы конфигурации и конкретную реализацию, скрытую за ними. Показывает, как создать собственную автоконфигурацию Spring Boot.

На этом завершается статья об использовании автоматической конфигурации, одного из четырех основных артефактов SpringBoot.

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