Где поставить @Bean в Spring Boot?
Мне интересно, какое лучшее место для приложения Spring Boot для регистрации дополнительного beans. У меня есть класс Main, который аннотируется с @SpringBootApplication
и beans, определенными в этом классе. Но когда я помещаю эти beans в другой класс, кажется, что они не регистрируются.
При чтении документации у меня появилась идея, что @SpringBootApplication
будет неявно искать классы, в которых есть аннотации @Bean
.
Итак, мои варианты:
-
Поместите все @Bean
аннотированные bean в мой основной класс
@SpringBootApplication
public class MyApplication {
@Bean
public Filter AuthenticationFilter() {
return new AuthenticationFilter();
}
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
-
Создайте класс конфигурации и отметьте, что с помощью @Configuration
@Configuration
public class MyConfiguration {
@Bean
public Filter AuthenticationFilter() {
return new AuthenticationFilter();
}
}
Есть ли лучший способ сделать это?
Ответы
Ответ 1
Это в значительной степени зависит от предпочтения, но обычно считается, что наилучшая практика заключается в том, чтобы подвергнуть экспоненциальному beans классу конфигурации, которые логически сгруппированы.
Например, у вас может быть несколько классов конфигурации с числом beans, содержащимся в каждом: класс конфигурации проверки подлинности с beans для AuthenticationProvider или UserDetailsService; класс конфигурации Thymeleaf, содержащий beans для различных диалектов тимелеафа и т.д.
Ответ 2
На самом деле, ваш выбор - нет стандартного spring, чтобы сказать, какой из них лучше, но при определении принципов проектирования ООП класса говорит, что класс должен быть loosely coupled
и highly cohesive
, should follow Single Responsibility Principle (SRP)
, Here
Coupling
→ Степень знания, которое класс имеет о другом классе
Cohesion
→ Степень, которая говорит, насколько хорошо сфокусирован ваш класс
SRP
→ Класс должен иметь только одну ответственность, должна быть только одна причина для изменения класса.
Таким образом, согласно принципам сплоченности и SRP, класс должен быть хорошо сфокусированным и иметь только одну ответственность.
Здесь в вашем случае у вас есть только 2 beans, но в будущем эти beans могут увеличиться. Поэтому следует следовать вашему второму пункту и создать другой класс для объявления bean.
И в моем выборе должно быть даже создано больше классов конфигурации. Поэтому один класс конфигурации должен иметь похожий тип beans.
Ответ 3
Да, включение бобов в класс @Configuration обычно является предпочтительным способом для Spring.
Это также один из способов, которыми Spring рекомендует внедрять взаимозависимости между компонентами. Это показано в следующем примере, скопированном из справочного руководства Spring здесь:
Кроме того, областью @Beans по умолчанию является SINGLETON, если вы укажете другую область, такую как PROTOTYPE, вызов будет передан исходному методу.
Посмотрите этот раздел в справочном руководстве по Spring
Ответ 4
Это зависит от личного выбора, и нет хорошего или плохого способа сделать это.
Как это предпочтительно или указывается в документации Spring Boot.
Поскольку аннотирование основного класса с помощью @SpringBootApplication
делает его удобным для Spring Bootstrap, приложение. Но он только ищет подпакеты, поэтому вложенная конфигурация внутри подпапки не будет автоматически обнаруживать @Bean
, это единственное, что нужно помнить, кроме всего этого о личных предпочтениях.
Ответ 5
Это зависит от того, где находится основной класс, который обычно имеет аннотации @SpringBootApplication
. Вы можете аннотировать этот основной класс с помощью @ComponentScan(basePackageClasses = HelloWorld.class)
. Здесь HelloWorld
содержит определения bean-компонентов, помеченные @Beans
, а класс помечен @Configurations
.
Контейнер Spring будет сканировать все подпакеты класса, указанного в аргументах @ComponentScan
. Вы также можете указать групповые символы вместо имени класса.
Ex:
@SpringBootApplication
@ComponentScan(basePackageClasses = HelloWorld.class)
public class DemoApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class);
}
}
**Bean Class:**
@Configuration
public class HelloWorld {
@Bean
public TweetUserSevice tweetUserSevice() {
return new TweetUserSeviceImpl();
}
}
Ответ 6
Это зависит от того, где находится основной класс, который обычно имеет аннотации @SpringBootApplication
. Вы можете аннотировать этот основной класс с помощью @ComponentScan(basePackageClasses = HelloWorld.class)
. Здесь HelloWorld
имеет определения, помеченные @Beans
, а класс помечен @Configurations
.
Контейнер Spring будет сканировать все подпакеты класса, указанного в аргументах @ComponentScan
. Вы также можете указать подстановочные знаки для аргумента basePackageClasses
вместо имени класса, как указано выше. Э.Г.
@SpringBootApplication
@ComponentScan(basePackageClasses = HelloWorld.class)
public class DemoApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class);
}
}
Класс бобов:
@Configuration
public class HelloWorld {
@Bean
public TweetUserSevice tweetUserSevice() {
return new TweetUserSeviceImpl();
}
}
Другой подход:
Обычно в больших проектах у нас будет несколько классов конфигурации Spring, содержащих определения bean-компонентов. Мы можем не беспокоиться о том, что весь класс бинов должен быть в подпакете основного класса. Что мы можем сделать, так это то, что у нас может быть один класс конфигурации master spring (но убедитесь, что этот класс конфигурации master spring находится в подпакете основного класса, чтобы аннотации @SpringBootApplication
автоматически определяли основной конфигурацию) и импортировали все остальные bean-компоненты классы.
У меня есть 2 класса бинов (TweetBeansConfig
, TweetSystemHealthBeansConfig
) в пакете com.ronak.tweet
(этот пакет не является подпакетом, где существует основной класс). У меня есть один класс конфигурации основной пружины (TweetMasterSpringConfig
), и этот класс находится в пакете, который является подпакетом, где находится мой основной класс.
package com.ronak.tweet.beans;
@Configuration
@Order(value=1)
@Import({
TweetBeansConfig.class,
TweetSystemHealthBeansConfig.class
})
public class TweetMasterSpringConfig {
public TweetMasterSpringConfig() {
System.out.println("Initilaizing master spring config");
}
}
package com.ronak.beans;
@Configuration
public class TweetBeansConfig {
@Bean
{
//
}
}
package com.ronak.beans;
@Configuration
public class TweetSystemHealthBeansConfig {
@Bean
{
//
}
}
Main class
package com.ronak.tweet;
@SpringBootApplication
public class DemoApplication extends SpringBootServletInitializer {
/**This is for registing REST layer for Jersey which implements jaxb. It will register all the classes which is in the pacakage com.ronak.tweet.rest. You can add comma separated package names too.
@Bean
ResourceConfig resourceConfig() {
return new ResourceConfig().packages("com.ronak.tweet.rest");
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class);
}
}