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

Какие аннотации управляют жизненным циклом бинов

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

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

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

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

Какие аннотации управляют жизненным циклом бинов

В Spring Framework есть несколько аннотаций и интерфейсов, которые управляют жизненным циклом бина (bean lifecycle).

1. @PostConstruct — инициализация после создания

// Вызывается ПОСЛЕ того, как бин создан и зависимости внедрены
@Service
public class UserService {
    private final UserRepository userRepository;
    private final CacheService cacheService;
    
    public UserService(UserRepository userRepository, CacheService cacheService) {
        this.userRepository = userRepository;
        this.cacheService = cacheService;
    }
    
    @PostConstruct
    public void initialize() {
        // Выполнится ПОСЛЕ конструктора и внедрения зависимостей
        // Можешь использовать все поля и зависимости
        System.out.println("UserService initialized");
        
        // Например: загрузить данные
        cacheService.loadAllUsers();
        cacheService.warmupCache();
    }
}

// Жизненный цикл:
// 1. Создание объекта (constructor)
// 2. Внедрение зависимостей
// 3. @PostConstruct методы

2. @PreDestroy — очистка перед удалением

// Вызывается перед удалением бина из контекста
@Configuration
public class DatabaseConfig {
    
    @Bean
    public DataSource dataSource() {
        return new HikariDataSource();
    }
}

@Service
public class DatabaseService {
    private final DataSource dataSource;
    
    public DatabaseService(DataSource dataSource) {
        this.dataSource = dataSource;
    }
    
    @PreDestroy
    public void cleanup() {
        // Выполнится перед удалением бина
        System.out.println("Closing database connections");
        
        if (dataSource instanceof HikariDataSource) {
            ((HikariDataSource) dataSource).close();
        }
    }
}

// Жизненный цикл:
// 1. Использование бина
// 2. @PreDestroy методы
// 3. Удаление бина

3. InitializingBean интерфейс

// Альтернатива @PostConstruct
import org.springframework.beans.factory.InitializingBean;

@Component
public class ConfigLoader implements InitializingBean {
    
    @Override
    public void afterPropertiesSet() throws Exception {
        // Вызывается после внедрения свойств
        System.out.println("Loading configuration");
        loadConfigFromFile();
    }
    
    private void loadConfigFromFile() {
        // ...
    }
}

// Эквивалент:
// @PostConstruct vs implements InitializingBean
// @PostConstruct рекомендуется (JSR-250), более явная семантика

4. DisposableBean интерфейс

// Альтернатива @PreDestroy
import org.springframework.beans.factory.DisposableBean;

@Component
public class ResourceManager implements DisposableBean {
    
    private FileWriter fileWriter;
    
    @PostConstruct
    public void init() throws Exception {
        fileWriter = new FileWriter("app.log");
    }
    
    @Override
    public void destroy() throws Exception {
        // Вызывается перед удалением бина
        System.out.println("Closing resources");
        if (fileWriter != null) {
            fileWriter.close();
        }
    }
}

5. @Bean initMethod и destroyMethod

// Определение методов жизненного цикла на уровне @Bean
@Configuration
public class BeanConfig {
    
    @Bean(initMethod = "start", destroyMethod = "stop")
    public ServiceClient serviceClient() {
        return new ServiceClient();
    }
}

public class ServiceClient {
    
    // Вызовется когда бин создан
    public void start() {
        System.out.println("Service client started");
    }
    
    // Вызовется при завершении контекста
    public void stop() {
        System.out.println("Service client stopped");
    }
}

6. BeanPostProcessor — обработка всех бинов

// Позволяет вмешаться в жизненный цикл ВСЕХ бинов
import org.springframework.beans.factory.config.BeanPostProcessor;

@Component
public class LoggingBeanPostProcessor implements BeanPostProcessor {
    
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) 
            throws BeansException {
        // Вызывается ДО инициализации (до @PostConstruct)
        System.out.println("Before init: " + beanName);
        return bean;
    }
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) 
            throws BeansException {
        // Вызывается ПОСЛЕ инициализации (после @PostConstruct)
        System.out.println("After init: " + beanName);
        return bean;
    }
}

// Порядок вызова:
// 1. postProcessBeforeInitialization
// 2. @PostConstruct или afterPropertiesSet()
// 3. postProcessAfterInitialization

7. Scope (область видимости) — @Scope

// Управляет жизненным циклом в смысле создания экземпляров

@Component
@Scope("singleton")  // (по умолчанию) Один экземпляр на приложение
public class SingletonService {
    @PostConstruct
    void init() {
        System.out.println("Singleton created once");
    }
}

@Component
@Scope("prototype")  // Новый экземпляр при каждом запросе
public class PrototypeService {
    @PostConstruct
    void init() {
        System.out.println("Prototype created for each injection");
    }
}

@Component
@Scope("request")  // Новый экземпляр для каждого HTTP запроса
public class RequestService {
    @PostConstruct
    void init() {
        System.out.println("Request scoped service");
    }
}

@Component
@Scope("session")  // Один экземпляр на HTTP сессию
public class SessionService {
    @PostConstruct
    void init() {
        System.out.println("Session scoped service");
    }
}

8. ApplicationContextAware — доступ к контексту

import org.springframework.context.ApplicationContextAware;

@Component
public class MyApplication implements ApplicationContextAware {
    
    private ApplicationContext context;
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) 
            throws BeansException {
        // Вызывается Spring для внедрения контекста
        this.context = applicationContext;
    }
    
    public void doSomething() {
        // Теперь можем получить любой бин из контекста
        SomeService service = context.getBean(SomeService.class);
    }
}

Полный жизненный цикл бина

@Component
public class CompleteLifecycle implements 
        InitializingBean, 
        DisposableBean,
        ApplicationContextAware {
    
    private ApplicationContext context;
    
    // 1. Конструктор
    public CompleteLifecycle() {
        System.out.println("1. Constructor");
    }
    
    // 2. Внедрение зависимостей
    @Autowired
    private SomeService someService;
    
    // 3. Aware интерфейсы
    @Override
    public void setApplicationContext(ApplicationContext context) {
        System.out.println("3. setApplicationContext");
        this.context = context;
    }
    
    // 4. BeanPostProcessor.postProcessBeforeInitialization
    
    // 5. @PostConstruct или afterPropertiesSet
    @PostConstruct
    public void postConstruct() {
        System.out.println("5. @PostConstruct");
    }
    
    @Override
    public void afterPropertiesSet() {
        System.out.println("5. afterPropertiesSet");
    }
    
    // 6. BeanPostProcessor.postProcessAfterInitialization
    
    // ... Использование бина
    
    // 7. @PreDestroy или destroy
    @PreDestroy
    public void preDestroy() {
        System.out.println("7. @PreDestroy");
    }
    
    @Override
    public void destroy() {
        System.out.println("7. destroy");
    }
}

Рекомендации

// ✅ РЕКОМЕНДУЕТСЯ: @PostConstruct и @PreDestroy
@Component
public class MyService {
    
    @PostConstruct
    void init() {
        // Инициализация
    }
    
    @PreDestroy
    void cleanup() {
        // Очистка
    }
}

// 🔶 Альтернатива: InitializingBean и DisposableBean (старый стиль)
// ❌ Избегай: InitMethod и destroyMethod (мало информации)
// ❌ BeanPostProcessor только если нужно влиять на все бины

Справочная таблица управления жизненным циклом бинов в Spring.