Поиск по сайту:

Весна @PostConstruct и @PreDestroy


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

Весна @PostConstruct

Когда мы аннотируем метод в Spring Bean аннотацией @PostConstruct, он выполняется после инициализации Spring Bean. У нас может быть только один метод, аннотированный аннотацией @PostConstruct. Эта аннотация является частью Common Annotations API и частью модуля JDK javax.annotation-api. Поэтому, если вы используете эту аннотацию в Java 9 или выше, вам придется явно добавить эту банку в свой проект. Если вы используете maven, то к нему следует добавить приведенную ниже зависимость.

<dependency>
	<groupId>javax.annotation</groupId>
	<artifactId>javax.annotation-api</artifactId>
	<version>1.3.2</version>
</dependency>

Если вы используете Java 8 или более раннюю версию, вам не нужно добавлять вышеуказанную зависимость.

Весна @PreDestroy

Когда мы аннотируем метод Spring Bean аннотацией PreDestroy, он вызывается, когда экземпляр компонента удаляется из контекста. Это очень важный момент, который нужно понять: если ваша область действия Spring bean является «прототипом», то она не полностью управляется контейнером Spring, и метод PreDestroy не будет вызываться. Если есть метод с именем shutdown или close, контейнер Spring попытается автоматически настроить их как методы обратного вызова при уничтожении bean-компонента.

Пример Spring @PostConstruct и @PreDestroy

Вот простой Spring bean с методами @PreDestroy.

package com.journaldev.spring;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class MyBean {

	public MyBean() {
		System.out.println("MyBean instance created");
	}

	@PostConstruct
	private void init() {
		System.out.println("Verifying Resources");
	}

	@PreDestroy
	private void shutdown() {
		System.out.println("Shutdown All Resources");
	}

	public void close() {
		System.out.println("Closing All Resources");
	}
}

Обратите внимание, что я также определил метод close для проверки, вызывается ли он при уничтожении нашего компонента. Вот мой простой класс конфигурации Spring.

package com.journaldev.spring;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration
public class MyConfiguration {
	
    @Bean
    @Scope(value="singleton")
    public MyBean myBean() {
	return new MyBean();
    }
	
}

Мне не нужно явно указывать мой компонент как синглтон, но позже я изменю его значение на «прототип» и посмотрю, что происходит с методами @PreDestroy. Вот мой основной класс, в котором я создаю контекст Spring и получаю несколько экземпляров MyBean.

package com.journaldev.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MySpringApp {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
		ctx.register(MyConfiguration.class);
		ctx.refresh();

		MyBean mb1 = ctx.getBean(MyBean.class);
		System.out.println(mb1.hashCode());

		MyBean mb2 = ctx.getBean(MyBean.class);
		System.out.println(mb2.hashCode());

		ctx.close();
	}

}

Когда мы запускаем класс выше, мы получаем следующий вывод.

MyBean instance created
Verifying Resources
1640296160
1640296160
Shutdown All Resources
Closing All Resources

Таким образом, метод @PostConstruct вызывается после создания экземпляра компонента. Когда контекст закрывается, он вызывает метод shutdown и close.

Spring @PostConstruct и @PreDestroy с областью действия прототипа

Просто измените значение области на прототип в MyConfiguration и запустите основной класс. Вы получите вывод, как показано ниже.

MyBean instance created
Verifying Resources
1640296160
MyBean instance created
Verifying Resources
1863374262

Итак, понятно, что контейнер Spring инициализирует bean-компонент при каждом запросе, вызывает его метод @PostConstruct и затем передает его клиенту. После этого Spring не управляет bean-компонентом, и в этом случае клиент должен выполнить всю очистку ресурсов, напрямую вызвав метод PreDestroy.

Резюме

@PreDestroy и важные аннотации для использования с управлением жизненным циклом Spring bean. Мы можем использовать их, чтобы убедиться, что bean-компонент правильно инициализирован, а затем закрыть все ресурсы, когда bean-компонент будет удален из контекста Spring.

Вы можете проверить полный код проекта в нашем репозитории GitHub.