Аннотация @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