← Назад к вопросам

Как Spring понимает, что использует не *.jar, а Starter

2.0 Middle🔥 281 комментариев
#Spring Boot и Spring Data#Spring Framework

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Как Spring понимает, что использует не *.jar, а Starter?

Этот вопрос касается механизма Spring Boot Starter'ов и того, как Spring Boot определяет и автоматически конфигурирует зависимости. Давайте разберемся.

Что такое Spring Boot Starter?

Starter — это специальная зависимость Spring Boot, которая:

  1. Содержит метаданные о нужных библиотеках
  2. Автоматически конфигурирует приложение
  3. Предоставляет sensible defaults (разумные настройки по умолчанию)

Структура обычного JAR vs Starter

Обычный JAR

my-library.jar
├── META-INF/
│   └── MANIFEST.MF (только описание артефакта)
└── com/example/
    └── MyClass.class

Spring Boot Starter

spring-boot-starter-web.jar
├── META-INF/
│   ├── MANIFEST.MF
│   └── spring.factories (← ВОТ ЭТО КЛЮЧЕВОЕ!)
│   └── spring-configuration-metadata.json
├── (сам стартер НЕ содержит кода, только метаданные!)

Как Spring Boot определяет Starter: spring.factories

Основной механизм — файл META-INF/spring.factories:

# spring-boot-starter-web.jar META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration

# spring-boot-starter-data-jpa.jar
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration

Spring Boot при запуске:

  1. Находит все spring.factories на classpath
  2. Загружает классы из EnableAutoConfiguration
  3. Применяет автоконфигурацию

Пример: Как работает spring-boot-starter-web

build.gradle:

dependencies {
    implementation "org.springframework.boot:spring-boot-starter-web:3.2.0"
}

Что происходит при сборке:

1. Gradle скачивает spring-boot-starter-web.jar
2. Spring Boot находит META-INF/spring.factories
3. Видит: DispatcherServletAutoConfiguration, ...
4. Автоматически создает бины:
   - DispatcherServlet
   - RequestMappingHandlerMapping
   - RequestMappingHandlerAdapter
   - Jackson ObjectMapper для JSON
   - ... и еще 50+ бинов

AutoConfiguration класс пример

@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({DispatcherServlet.class})
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@AutoConfigureBefore({ServletWebServerFactoryAutoConfiguration.class})
public class DispatcherServletAutoConfiguration {
    
    @Configuration
    @Conditional(DispatcherServletRegistrationCondition.class)
    @ConditionalOnClass(ServletRegistration.class)
    protected static class DispatcherServletConfiguration {
        
        @Bean(name = DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
        public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {
            DispatcherServlet dispatcherServlet = new DispatcherServlet();
            // Применяем свойства из application.yml
            webMvcProperties.getDispatcher().ifPresent(dispatcherServlet::setDispatchOptionsRequest);
            return dispatcherServlet;
        }
        
        @Bean
        public ServletRegistrationBean<DispatcherServlet> dispatcherServletRegistration(
            DispatcherServlet dispatcherServlet,
            WebMvcProperties webMvcProperties,
            ObjectProvider<MultipartConfigElement> multipartConfig) {
            ServletRegistrationBean<DispatcherServlet> registration = 
                new ServletRegistrationBean<>(dispatcherServlet, "/");
            registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
            registration.setLoadOnStartup(
                webMvcProperties.getServlet().getLoadOnStartup());
            multipartConfig.ifAvailable(registration::setMultipartConfig);
            return registration;
        }
    }
}

Как Spring Boot находит AutoConfiguration

// В Spring Boot Application Context инициализации:

1. SpringApplication.run() запускается

2. SpringApplication создает AnnotatedBeanDefinitionReader

3. BeanDefinitionParser находит аннотацию @SpringBootApplication

4. Которая содержит @EnableAutoConfiguration

5. @EnableAutoConfiguration включает AutoConfigurationImportSelector

6. AutoConfigurationImportSelector.selectImports():
   - Использует SpringFactoriesLoader
   - Загружает META-INF/spring.factories из всех JAR'ов
   - Фильтрует по условиям (@ConditionalOnClass, etc.)
   - Возвращает список AutoConfiguration классов

7. Spring регистрирует все AutoConfiguration классы как Configuration beans

8. Spring создает бины согласно AutoConfiguration

Условия автоконфигурации

Spring использует аннотации-условия:

@ConditionalOnClass(ClassName.class)          // Если класс есть на classpath
@ConditionalOnMissingClass(ClassName.class)   // Если класса НЕ т на classpath
@ConditionalOnBean(BeanType.class)            // Если бин есть в контексте
@ConditionalOnMissingBean(BeanType.class)     // Если бина нет в контексте
@ConditionalOnProperty(name = "prop")         // Если свойство установлено
@ConditionalOnWebApplication                  // Если это веб приложение
@ConditionalOnExpression("#{...}")            // SpEL выражение

Пример:

@Configuration
@ConditionalOnClass(DataSource.class)  // Если JDBC на classpath
@ConditionalOnMissingBean(DataSource.class) // И нет кастомного DataSource
public class DataSourceAutoConfiguration {
    
    @Bean
    @ConditionalOnProperty("spring.datasource.url")
    public DataSource dataSource(DataSourceProperties properties) {
        return DataSourceBuilder.create()
            .url(properties.getUrl())
            .username(properties.getUsername())
            .password(properties.getPassword())
            .build();
    }
}

Практический пример: spring-boot-starter-data-jpa

build.gradle:

dependencies {
    implementation "org.springframework.boot:spring-boot-starter-data-jpa"
}

Что в spring.factories:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration

Что происходит:

1. HibernateJpaAutoConfiguration проверяет:
   - @ConditionalOnClass(Entity.class, EntityManager.class)
   - @ConditionalOnMissingBean(JpaVendorAdapter.class)

2. Если условия выполнены, создает:
   - SessionFactory
   - EntityManagerFactory  
   - PlatformTransactionManager

3. JpaRepositoriesAutoConfiguration проверяет:
   - @ConditionalOnClass(JpaRepository.class)
   - @ConditionalOnMissingBean(RepositoryConfigurationDelegate.class)

4. Если условия выполнены, включает:
   - @EnableJpaRepositories
   - Сканирует @Repository интерфейсы
   - Создает прокси для каждого Repository

Как разработчик может видеть, какие AutoConfiguration используются

# При запуске с debug режимом:
java -jar application.jar --debug

Или в application.properties:

logging.level.org.springframework.boot.autoconfigure=DEBUG

Вывод:

=========================
AUTO-CONFIGURATION REPORT
=========================

Positive matches:
-----------
   DispatcherServletAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet' (OnClassCondition)
      - @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)

   DataSourceAutoConfiguration matched:
      - @ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType' (OnClassCondition)
      - @ConditionalOnMissingBean (types: javax.sql.DataSource, javax.sql.XADataSource; SearchStrategy: all) did not find any beans (OnBeanCondition)

Negative matches:
-----------
   DataSourceTransactionManagerAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'org.springframework.jdbc.support.JdbcTransactionManager' (OnClassCondition)

Отключение определенной AutoConfiguration

@SpringBootApplication(
    exclude = {
        DataSourceAutoConfiguration.class,
        HibernateJpaAutoConfiguration.class
    }
)
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Или в application.properties:

spring.autoconfigure.exclude=\
  org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
  org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration

Заключение

Spring Boot определяет Starter'ы через:

spring.factories — метаданные с AutoConfiguration классами ✅ SpringFactoriesLoader — загружает spring.factories из всех JAR'ов ✅ AutoConfigurationImportSelector — регистрирует AutoConfiguration ✅ @ConditionalOn* аннотации — проверяют условия применения ✅ Sensible defaults — автоматическая конфигурация с разумными значениями

Это делает Spring Boot таким удобным: вместо ручной конфигурации десятков классов, вы просто добавляете одну строку в build.gradle!

Как Spring понимает, что использует не *.jar, а Starter | PrepBro