Java 在 Spring Boot 中将 @Bean 放在哪里?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29146019/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 07:26:55  来源:igfitidea点击:

Where to put @Bean in Spring Boot?

javaspringspring-boot

提问by Marco

I am wondering what the best place would be for a Spring Boot app to register additional beans. I have a Main class that is annotated with @SpringBootApplicationand beans defined in that class are picked up. But when i put those beans in another class it seems that the are not being registered.

我想知道 Spring Boot 应用程序注册额外 bean 的最佳位置是什么。我有一个带有注释的 Main 类,@SpringBootApplication并选取了该类中定义的 bean。但是当我把这些 bean 放在另一个类中时,它们似乎没有被注册。

When reading the documentation i got the idea that the @SpringBootApplicationwould implicitly search for classes that have @Beanannotations in them.

在阅读文档时,我认为@SpringBootApplication将隐式搜索其中包含@Bean注释的类。

So my options are now:

所以我现在的选择是:

  1. Put all @Beanannotated bean in my main class

    @SpringBootApplication
    public class MyApplication {
    
        @Bean
        public Filter AuthenticationFilter() {
            return new AuthenticationFilter();
        }
    
        public static void main(String[] args) {
            SpringApplication.run(MyApplication.class, args);
        }
    }
    
  2. Create a configuration class and annotate that with @Configuration

    @Configuration
    public class MyConfiguration {
        @Bean
        public Filter AuthenticationFilter() {
            return new AuthenticationFilter();
        }
    }
    
  1. 将所有带@Bean注释的 bean 放在我的主类中

    @SpringBootApplication
    public class MyApplication {
    
        @Bean
        public Filter AuthenticationFilter() {
            return new AuthenticationFilter();
        }
    
        public static void main(String[] args) {
            SpringApplication.run(MyApplication.class, args);
        }
    }
    
  2. 创建一个配置类并用 @Configuration

    @Configuration
    public class MyConfiguration {
        @Bean
        public Filter AuthenticationFilter() {
            return new AuthenticationFilter();
        }
    }
    

Is there a better way of doing this?

有没有更好的方法来做到这一点?

回答by Moshiour

It depends on personal choices and there is no good or bad way to do it. As it is preferred or showed way in documentation of Spring Boot references.

这取决于个人选择,没有好坏之分。因为它是首选或在 Spring Boot 参考文档中显示的方式。

As annotating main class with @SpringBootApplicationmakes it convenient to Bootstrap spring app. But it does only looks for subpackages so nesting configuration inside subfolder would not detect the @Beanautomatically that is the only thing to remember other than it's all about personal preferences.

作为注释主类,@SpringBootApplication可以方便 Bootstrap spring 应用程序。但它只查找子包,因此子文件夹中的嵌套配置不会@Bean自动检测到除了个人喜好之外唯一要记住的事情。

回答by Daniel Cottone

It is pretty much a matter of preference, but it is generally considered best practice to put exposed beans in configuration classes, which are logically grouped.

这几乎是一个偏好问题,但通常认为将暴露的 bean 放在逻辑分组的配置类中是最佳实践。

For example, you might have several configuration classes with a number of beans contained within each: An authentication configuration class with beans for AuthenticationProvider or UserDetailsService; a Thymeleaf configuration class containing beans for various Thymeleaf dialects, etc.

例如,您可能有多个配置类,每个配置类中包含多个 bean: 身份验证配置类,带有用于 AuthenticationProvider 或 UserDetailsS​​ervice 的 bean;包含用于各种 Thymeleaf 方言等的 bean 的 Thymeleaf 配置类。

回答by Naresh Joshi

Actually, it is your choice there is no spring standard present to tell which one is best but while defining a class OOP design principles says A class should be loosely coupledand highly cohesive, should follow Single Responsibility Principle (SRP), Here

其实,这是你的选择没有春天标准的现地告诉哪一个是最好的,但在定义一个类OOP的设计原理说,一个类应该是loosely coupledhighly cohesive,宜follow Single Responsibility Principle (SRP),这里

Coupling--> Degree of knowledge a class has about another class

Coupling--> 一个班级对另一个班级的了解程度

Cohesion--> Degree which tells how well focused your class is

Cohesion--> 程度说明你的班级有多专注

SRP--> A class should have only one responsibility, there should be only one reason to change a class.

SRP--> 一个类应该只有一个职责,换一个类应该只有一个原因。

So according to cohesion and SRP principle class should be well focused and have only one responsibility.

所以根据cohesion和SRP原则,class应该是重点突出的,只有一个职责。

Here in your case you have only 2 beans but in future, these beans might increase. So should follow your second point and create another class for your bean declaration.

在您的情况下,您只有 2 个豆子,但将来这些豆子可能会增加。所以应该遵循你的第二点并为你的 bean 声明创建另一个类。

And In my choice should even create more configuration classes, So one configuration class should have a similar type of beans.

并且在我的选择中甚至应该创建更多的配置类,所以一个配置类应该有类似类型的bean。

回答by Tomasz Kubiak

Yes, including your beans inside the @Configuration class is usually the preferred way for Spring.

是的,在 @Configuration 类中包含 bean 通常是 Spring 的首选方式。

This is also one of the ways Spring recommends injecting inter-dependencies between beans is shown in the following sample copied from the Spring's reference guide here:

这也是春建议注射豆从Spring的参考指南复制下面的示例中显示之间的相互依存关系的方法之一在这里

Additionally, the default scope of @Beans is SINGLETON, if you specify a different scope such as PROTOTYPE the call will be passed to the original method. Have a look at this section in the Spring Reference Guide

此外,@Beans 的默认范围是 SINGLETON,如果您指定不同的范围,例如 PROTOTYPE,则调用将传递给原始方法。查看Spring 参考指南中的这一部分

回答by Ronak Jain

It depends on where the main class is located which has generally @SpringBootApplicationannotations. You can annotate this main class with @ComponentScan(basePackageClasses = HelloWorld.class). Here HelloWorldhas bean definitions annotated with @Beansand the class is annotated with @Configurations.

这取决于通常具有@SpringBootApplication注释的主类所在的位置。您可以使用@ComponentScan(basePackageClasses = HelloWorld.class). 这里的HelloWorldbean 定义@Beans@Configurations.

Spring container will scan all the sub-packages of the class specified in @ComponentScanarguments. You can also give wild card entries instead of class name.

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

}

回答by Ronak Jain

It depends on where the main class is located which has generally @SpringBootApplicationannotations. You can annotate this main class with @ComponentScan(basePackageClasses = HelloWorld.class). Here HelloWorldhas had definitions annotated with @Beansand the class is annotated with @Configurations. Spring container will scan all the sub-packages of the class specified in @ComponentScanarguments. You can also give wild card entries for basePackageClassesargument instead of class name as specified above. E.g.

这取决于通常具有@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);
    }

}

Bean Class:

豆类:

@Configuration
public class HelloWorld {

    @Bean
    public TweetUserSevice tweetUserSevice() {
        return new TweetUserSeviceImpl();
    }      
}

Another approach:

另一种方法:

Generally in big projects, we will have multiple spring config classes containing bean definitions. We can avoid worrying about that all the bean class should be in sub-package of main class. What we can do is that we can have a single master spring config class(but make sure this master spring config class is under sub-package of main class so that @SpringBootApplicationannotations automatically detects the master config) and import all the other bean classes.

通常在大项目中,我们会有多个包含 bean 定义的 spring 配置类。我们可以避免担心所有的bean类都应该在主类的子包中。我们可以做的是,我们可以有一个主 spring 配置类(但要确保这个主 spring 配置类在主类的子包下,以便@SpringBootApplication注解自动检测主配置)并导入所有其他 bean 类。

I have 2 bean classes (TweetBeansConfig, TweetSystemHealthBeansConfig) in the package com.ronak.tweet(This package is not sub-package where main class exists). I have one master spring config class (TweetMasterSpringConfig) and this class resides in package which is sub-package where my main class resides.

我在包中有 2 个 bean 类 ( TweetBeansConfig, TweetSystemHealthBeansConfig) com.ronak.tweet(此包不是存在主类的子包)。我有一个主 spring 配置类 ( 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);
      }

}