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

Для чего нужна аннотация @Configuration?

1.8 Middle🔥 141 комментариев
#Spring Framework

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

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

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

Для чего нужна аннотация @Configuration

@Configuration — это ключевая аннотация Spring Framework, которая обозначает класс как источник определения бинов (bean definitions) для контейнера IoC.

Основное предназначение

// @Configuration обозначает класс конфигурации
@Configuration
public class AppConfig {
    
    // @Bean обозначает методы, которые создают бины
    @Bean
    public DataSource dataSource() {
        return new HikariDataSource();
    }
    
    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

// Spring автоматически создаст бины и добавит их в контейнер

Как @Configuration работает

  1. Spring сканирует приложение и находит классы с @Configuration
  2. Для каждого класса Spring создает специальный прокси (cglib proxy)
  3. Прокси перехватывает вызовы методов с @Bean аннотацией
  4. Результаты кэшируются так, чтобы один и тот же бин возвращался всегда
  5. Методы с параметрами получают зависимости из контейнера автоматически
@Configuration
public class DatabaseConfig {
    
    @Bean
    public DataSource dataSource() {
        System.out.println("Creating DataSource");
        return new HikariDataSource();
    }
    
    @Bean
    public UserRepository userRepository(DataSource dataSource) {
        // dataSource будет автоматически введен
        // Это тот же бин, что был создан выше (синглтон)
        return new UserRepository(dataSource);
    }
}

// При запуске Spring:
// 1. Creating DataSource (выводится один раз)
// 2. userRepository получает то же самое DataSource

@Configuration vs без аннотации

Без @Configuration (НЕПРАВИЛЬНО)

public class BadConfig {
    
    @Bean
    public DataSource dataSource() {
        System.out.println("Creating DataSource");
        return new HikariDataSource();
    }
    
    @Bean
    public UserRepository userRepository(DataSource dataSource) {
        return new UserRepository(dataSource);
    }
    
    @Bean
    public OrderRepository orderRepository() {
        // Проблема: создает НОВЫЙ DataSource вместо использования бина!
        DataSource ds = dataSource();  // Обычный вызов метода
        return new OrderRepository(ds);
    }
}

// Результат:
// - Creating DataSource выведется ДВАЖДЫ или ТРИЖДЫ
// - Разные компоненты получат разные DataSource'ы (не синглтон!)
// - Может привести к утечкам ресурсов

С @Configuration (ПРАВИЛЬНО)

@Configuration  // Spring обернет класс в прокси
public class GoodConfig {
    
    @Bean
    public DataSource dataSource() {
        System.out.println("Creating DataSource");
        return new HikariDataSource();
    }
    
    @Bean
    public UserRepository userRepository(DataSource dataSource) {
        // dataSource пришел из контейнера
        return new UserRepository(dataSource);
    }
    
    @Bean
    public OrderRepository orderRepository(DataSource dataSource) {
        // Тот же dataSource благодаря @Configuration
        return new OrderRepository(dataSource);
    }
}

// Результат:
// - Creating DataSource выведется один раз
// - Все компоненты используют один синглтон DataSource
// - Правильное управление ресурсами

Аннотация @Bean

Аннотация @Bean обозначает метод, который производит бин для контейнера:

@Configuration
public class AppConfig {
    
    // Стандартное использование
    @Bean
    public UserService userService() {
        return new UserService();
    }
    
    // С явным именем бина
    @Bean(name = "primaryDataSource")
    public DataSource dataSource() {
        return new HikariDataSource();
    }
    
    // С инициализацией и очисткой
    @Bean(initMethod = "init", destroyMethod = "cleanup")
    public Cache cache() {
        return new RedisCache();
    }
    
    // С условием
    @Bean
    @ConditionalOnProperty(name = "cache.enabled", havingValue = "true")
    public CacheManager cacheManager() {
        return new CacheManager();
    }
}

Внедрение зависимостей в методы

@Configuration
public class ServiceConfig {
    
    @Bean
    public DatabaseConnection dbConnection() {
        return new DatabaseConnection();
    }
    
    // Способ 1: параметр метода
    @Bean
    public UserService userService(DatabaseConnection conn) {
        return new UserService(conn);
    }
    
    // Способ 2: конструктор конфига (если нужна одна зависимость)
    private final AppProperties appProps;
    
    public ServiceConfig(AppProperties appProps) {
        this.appProps = appProps;
    }
    
    @Bean
    public EmailService emailService() {
        return new EmailService(appProps.getSmtpServer());
    }
}

Полный пример приложения

// application.properties
// spring.datasource.url=jdbc:mysql://localhost:3306/mydb
// spring.datasource.username=root
// spring.datasource.password=password

@Configuration
public class ApplicationConfig {
    
    @Bean
    public DataSource dataSource() {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
        config.setUsername("root");
        config.setPassword("password");
        return new HikariDataSource(config);
    }
    
    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
    
    @Bean
    public UserRepository userRepository(JdbcTemplate jdbcTemplate) {
        return new UserRepository(jdbcTemplate);
    }
    
    @Bean
    public UserService userService(UserRepository userRepository) {
        return new UserService(userRepository);
    }
}

// Использование в приложении
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(Application.class);
        
        // Получить бин
        UserService userService = context.getBean(UserService.class);
        userService.createUser("john");
    }
}

@Configuration vs @Component

// @Component
@Component
public class SimpleComponent {
    // Это просто компонент, Spring создает один экземпляр
}

// @Configuration
@Configuration
public class ConfigClass {
    @Bean
    public SomeService someService() {
        return new SomeService();
    }
}

// Разница:
// - @Component: сам по себе бин
// - @Configuration: класс с методами, которые создают бины
// - @Configuration обертывается в прокси для правильного кэширования

Nested @Configuration

@Configuration
public class OuterConfig {
    
    @Bean
    public DataSource dataSource() {
        return new HikariDataSource();
    }
    
    @Configuration
    public static class InnerConfig {
        @Bean
        public UserRepository userRepository(DataSource dataSource) {
            return new UserRepository(dataSource);
        }
    }
}

Важные особенности

  1. Синглтоны по умолчанию
@Configuration
public class Config {
    @Bean
    public MyService myService() {
        return new MyService();  // Создается один раз и кэшируется
    }
}
  1. Автоматическое разрешение зависимостей
@Bean
public B beanB(A beanA) {  // beanA автоматически внедряется
    return new B(beanA);
}
  1. Порядок инициализации
@Bean
public DataSource dataSource() { ... }

@Bean
public JdbcTemplate jdbcTemplate(DataSource ds) {
    // dataSource будет создан ДО этого метода
    return new JdbcTemplate(ds);
}

Современная альтернатива

В Spring Boot 3.0+ можно использовать @Configuration с proxyBeanMethods = false для лучшей производительности:

@Configuration(proxyBeanMethods = false)
public class FastConfig {
    @Bean
    public DataSource dataSource() {
        return new HikariDataSource();
    }
}

// Важно: если вам НЕ нужна гарантия синглтонов от прокси

Итог

@Configuration — это мощная аннотация, которая:

  1. Обозначает класс как источник конфигурации
  2. Позволяет определять бины через методы
  3. Гарантирует синглтоны и правильное кэширование благодаря прокси
  4. Обеспечивает автоматическое разрешение зависимостей
  5. Создает декларативную конфигурацию приложения

Это один из основных механизмов, благодаря которому Spring Framework реализует инверсию управления (IoC) и внедрение зависимостей (DI).

Для чего нужна аннотация @Configuration? | PrepBro