Весенняя аннотация @Configuration
Методы определения Spring @Bean. Таким образом, контейнер Spring может обрабатывать класс и генерировать Spring Beans для использования в приложении.
Весна @Конфигурация
Внедрение зависимостей Spring. Давайте разберемся, как создавать классы конфигурации Spring. Давайте создадим простой класс java bean.
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 Configuration.
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 загружает bean-компоненты в свой контекст еще до того, как мы его запросили. Это делается для того, чтобы убедиться, что все bean-компоненты правильно настроены, а приложение работает быстро, если что-то пойдет не так. Также должен быть вызван 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 bean-компонентов по умолчанию является Singleton. Мы можем изменить его с помощью аннотации @Scope
.
Что, если мы удалим аннотацию @Configuration?
Что произойдет, если мы удалим аннотацию @Configuration из класса MyConfiguration. Вы заметите, что он по-прежнему работает так, как ожидалось, а bean-компоненты 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 ведет себя так, как мы хотим. Если вы не хотите использовать аннотацию @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 Configuration, мы рассмотрим другие аннотации Spring в будущих сообщениях.
Вы можете загрузить пример кода из нашего репозитория GitHub.