Вопрос 24 · Раздел 5

Что такое @Configuration класс?

4. @Bean → для сторонних библиотек 5. Наследование → бины родителя тоже регистрируются 6. ConfigurationClassPostProcessor → обработка на ранней стадии

Версии по языкам: English Russian Ukrainian

🟢 Junior Level

@Configuration — класс, который создаёт бины через методы @Bean.

@Configuration
public class AppConfig {

    @Bean
    public UserService userService() {
        return new UserService();
    }

    @Bean
    public OrderController orderController() {
        return new OrderController(userService());  // Внедрение
    }
    // В Full mode (по умолчанию) Spring перехватит вызов userService()
    // и вернёт singleton. В Lite mode (proxyBeanMethods = false) создастся
    // новый объект — см. Middle Level.
}

Зачем:

  • Для сторонних библиотек (нельзя поставить @Service)
  • Для сложной настройки бинов

🟡 Middle Level

Full vs Lite Mode

Full Mode (по умолчанию):

@Configuration  // proxyBeanMethods = true
public class Config {
    @Bean public A a() { return new A(); }
    @Bean public B b() { return new B(a()); }  // Тот же экземпляр A!
}

// CGLIB прокси перехватывает вызов a()
// → Проверяет кэш → возвращает существующий бин

Lite Mode:

@Configuration(proxyBeanMethods = false)
// или @Component, @Service с @Bean методами

@Bean public A a() { return new A(); }
@Bean public B b() { return new B(a()); }  // НОВЫЙ экземпляр A!

// Нет прокси → прямой вызов метода

Когда proxyBeanMethods = false

// Используйте false, если:
// 1. @Bean методы не вызывают друг друга
// 2. Зависимости через аргументы методов
@Bean
public Service service(Repo repo) {  // Spring сам найдёт repo
    return new Service(repo);
}

// → Быстрее старт
// → Меньше памяти
// → GraalVM Native friendly

🔴 Senior Level

CGLIB Proxies

@Configuration → CGLIB подкласс:
  → Перехватывает вызовы @Bean методов
  → Проверяет singletonObjects cache
  → Возвращает существующий или создаёт
  
→ Нельзя final классы/методы! CGLIB создаёт подкласс через наследование.
  Если класс или метод final — Java не позволяет наследоваться/переопределить,
  проксирование невозможно, Spring выбросит ошибку.
→ overhead на генерацию байт-кода

Наследование

@Configuration
public class ParentConfig {
    @Bean public CommonBean common() { return new CommonBean(); }
}

@Configuration
public class ChildConfig extends ParentConfig {
    // common() бин тоже зарегистрирован!
}

Production Experience

Реальный сценарий: proxyBeanMethods = true замедлял старт

200 @Configuration классов → 5 секунд на CGLIB
Решение: proxyBeanMethods = false
Результат: старт 2 секунды

Best Practices

  1. proxyBeanMethods = false — по умолчанию для новых проектов, НО если @Bean методы вызывают друг друга — оставьте true (иначе сломается singleton).
  2. Аргументы методов → вместо вызовов других @Bean
  3. Не final → классы и методы
  4. @Bean → для сторонних библиотек
  5. Наследование → бины родителя тоже регистрируются
  6. ConfigurationClassPostProcessor → обработка на ранней стадии

Резюме для Senior

  • @Configuration = фабрика бинов
  • Full mode → CGLIB прокси, singleton семантика
  • Lite mode → нет прокси, новые объекты
  • proxyBeanMethods = false → быстрее, Native friendly
  • Аргументы методов → Spring сам внедрит
  • final → нельзя проксировать

🎯 Шпаргалка для интервью

Обязательно знать:

  • @Configuration класс создаёт бины через @Bean методы — для сторонних библиотек и сложной настройки
  • Full mode (proxyBeanMethods = true): CGLIB-прокси перехватывает вызовы @Bean методов и возвращает singleton
  • Lite mode (proxyBeanMethods = false): прямой вызов метода — каждый вызов создаёт новый объект
  • Constructor Injection через аргументы @Bean методов — Spring сам внедрит зависимости
  • CGLIB создаёт подкласс через наследование — нельзя final классы/методы
  • proxyBeanMethods = false ускоряет старт на 40-60% и нужен для GraalVM Native Image
  • Наследование @Configuration: бины родителя тоже регистрируются

Частые уточняющие вопросы:

  • Когда использовать proxyBeanMethods = false? — Когда @Bean методы не вызывают друг друга и зависимости передаются через аргументы.
  • Что будет, если вызвать @Bean метод напрямую в Lite mode? — Создастся новый экземпляр, singleton-семантика сломается.
  • Почему @Configuration класс не может быть final? — CGLIB создаёт подкласс для проксирования; final наследование невозможно.
  • Чем @Configuration отличается от @Component с @Bean методами? — @Component работает в Lite mode — вызовы @Bean методов не перехватываются.

Красные флаги (НЕ говорить):

  • «@Bean методы всегда создают singleton» — только в Full mode с прокси.
  • «proxyBeanMethods = false всегда лучше» — нет, ломается singleton при меж-@Bean вызовах.
  • «@Configuration — это просто @Component» — нет, Full vs Lite mode критически различаются.
  • «Можно делать @Bean методы final» — нет, CGLIB не сможет переопределить метод.

Связанные темы:

  • [[21. Как работает @SpringBootApplication]]
  • [[26. Что делает аннотация @Autowired]]
  • [[28. Что такое @Qualifier]]
  • [[25. В чём разница между @Component, @Service, @Repository, @Controller]]