Аннотация @Configuration в Spring

Аннотация @Configuration Spring является частью основного фреймворка Spring. Аннотация Spring Configuration указывает, что у класса есть методы определения @Bean. Таким образом, контейнер Spring может обрабатывать класс и создавать Spring Beans, которые будут использоваться в приложении.

Spring @Configuration

Аннотация @Configuration Spring позволяет нам использовать аннотации для внедрения зависимостей. Давайте разберемся, как создавать классы конфигурации Spring. Создадим простой класс бина на языке Java.

package com.journaldev.spring;

public class MyBean {

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

Прежде чем мы будем использовать какие-либо классы фреймворка Spring, мы должны добавить зависимости в проект Maven.

<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context</artifactId>
		<version>5.0.6.RELEASE</version>
</dependency>

Теперь создадим класс конфигурации Spring.

package com.journaldev.spring;

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

@Configuration
public class MyConfiguration {

    @Bean
    public MyBean myBean() {
		return new MyBean();
	}
	
}

Напишем простой класс и настроим наш простой класс конфигурации Spring.

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);

		// MyBean mb2 = ctx.getBean(MyBean.class);

		ctx.close();
	}

}

Если вы запустите вышеуказанное приложение, оно выведет следующий результат:

May 23, 2018 12:34:54 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@ff5b51f: startup date [Wed May 23 12:34:54 IST 2018]; root of context hierarchy
MyBean instance created
May 23, 2018 12:34:54 PM org.springframework.context.support.AbstractApplicationContext doClose
INFO: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@ff5b51f: startup date [Wed May 23 12:34:54 IST 2018]; root of context hierarchy

Обратите внимание, что Spring загружает бины в свой контекст до того, как мы их даже запросим. Это сделано для того, чтобы убедиться, что все бины правильно настроены, и приложение быстро завершит работу, если что-то пойдет не так. Также необходимо вызвать ctx.refresh(), иначе мы получим следующую ошибку при попытке получить какой-либо бин из контекста.

Exception in thread "main" java.lang.IllegalStateException: org.springframework.context.annotation.AnnotationConfigApplicationContext@f0f2775 has not been refreshed yet
	at org.springframework.context.support.AbstractApplicationContext.assertBeanFactoryActive(AbstractApplicationContext.java:1076)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1106)
	at com.journaldev.spring.MySpringApp.main(MySpringApp.java:11)

Если вы закомментируете участки кода, где я получаю экземпляры MyBean, вы заметите, что он не вызывает конструктор MyBean. Это потому, что по умолчанию область видимости бинов Spring – Singleton. Мы можем изменить это, используя аннотацию @Scope.

Что если мы удалим @Configuration аннотацию?

Что произойдет, если мы удалим аннотацию @Configuration из класса MyConfiguration. Вы заметите, что это все равно работает ожидаемым образом, и бины Spring зарегистрированы и извлекаются как синглетон-классы. Но в этом случае, если мы вызовем метод myBean(), то это будет обычный вызов метода Java, и мы получим новый экземпляр MyBean, и он не останется синглетоном. Чтобы доказать это, давайте определим еще один бин, который будет использовать экземпляр MyBean.

package com.journaldev.spring;

public class MyBeanConsumer {

	public MyBeanConsumer(MyBean myBean) {
		System.out.println("MyBeanConsumer created");
		System.out.println("myBean hashcode = "+myBean.hashCode());
	}

}

Наш обновленный класс конфигурации Spring:

package com.journaldev.spring;

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

//@Configuration
public class MyConfiguration {

	@Bean
    public MyBean myBean() {
		return new MyBean();
	}
	
	@Bean
    public MyBeanConsumer myBeanConsumer() {
		return new MyBeanConsumer(myBean());
	}
}

Теперь, когда мы запускаем класс MySpringApp, он генерирует следующий вывод.

MyBean instance created
MyBean instance created
MyBeanConsumer created
myBean hashcode = 1647766367

Таким образом, MyBean больше не является синглтоном, теперь давайте снова аннотируем класс MyConfiguration аннотацией @Configuration и запустим класс MySpringApp. В этот раз вывод будет таким.

MyBean instance created
MyBeanConsumer created
myBean hashcode = 1095088856

Поэтому лучше использовать аннотацию @Configuration с классами конфигурации, чтобы убедиться, что наш контейнер Spring ведет себя так, как мы этого хотим. Если вы по каким-то странным причинам не хотите использовать аннотацию @Configuration, мы все равно можем создать наш класс конфигурации, не вызывая метод myBean(), а вместо этого использовать переменную экземпляра MyBean, настроенную через аннотацию @Autowired. Что-то вроде следующего кода тоже будет работать.

package com.journaldev.spring;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

//@Configuration
public class MyConfiguration {

	@Autowired
	MyBean myBean;
	
	@Bean
    public MyBean myBean() {
		return new MyBean();
	}
	
	@Bean
    public MyBeanConsumer myBeanConsumer() {
		return new MyBeanConsumer(myBean);
	}
}

Вот и все, что касается аннотации конфигурации Spring. Мы рассмотрим другие аннотации Spring в будущих сообщениях.

Вы можете скачать пример кода из нашего GitHub Repository.

Source:
https://www.digitalocean.com/community/tutorials/spring-configuration-annotation