Подтвердить что ты не робот

Где поставить @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();
        }
    }
    

Есть ли лучший способ сделать это?

4b9b3361

Ответ 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);
      }

}