web-dev-qa-db-fra.com

Où mettre @Bean dans Spring Boot?

Je me demande quel serait le meilleur endroit pour une application Spring Boot pour enregistrer des haricots supplémentaires. J'ai une classe principale annotée avec @SpringBootApplication et les haricots définis dans cette classe sont ramassés. Mais quand je mets ces haricots dans une autre classe, il semble qu'ils ne soient pas enregistrés.

En lisant la documentation, j'ai eu l'idée que le @SpringBootApplication rechercherait implicitement les classes qui ont @Bean annotations en eux.

Donc, mes options sont maintenant:

  1. Met tout @Bean haricot annoté dans ma classe principale

    @SpringBootApplication
    public class MyApplication {
    
        @Bean
        public Filter AuthenticationFilter() {
            return new AuthenticationFilter();
        }
    
        public static void main(String[] args) {
            SpringApplication.run(MyApplication.class, args);
        }
    }
    
  2. Créez une classe de configuration et annotez-la avec @Configuration

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

Existe-t-il une meilleure façon de le faire?

38
Marco

C'est plutôt une question de préférence, mais il est généralement considéré comme la meilleure pratique de placer les beans exposés dans des classes de configuration, qui sont regroupées de manière logique.

Par exemple, vous pouvez avoir plusieurs classes de configuration contenant un certain nombre de beans: Une classe de configuration d'authentification avec des beans pour AuthenticationProvider ou UserDetailsService; une classe de configuration Thymeleaf contenant des haricots pour divers dialectes Thymeleaf, etc.

15
Daniel Cottone

En fait, c’est votre choix qu’il n’y ait pas de standard printanier pour indiquer laquelle est la meilleure mais lorsque vous définissez une classe OOP, les principes de conception indiquent qu’une classe doit être loosely coupled Et highly cohesive, Devrait follow Single Responsibility Principle (SRP), ici

Coupling -> Degré de connaissance d'une classe sur une autre classe

Cohesion -> Degré décrivant le degré de concentration de votre classe

SRP -> Une classe ne devrait avoir qu'une seule responsabilité, il devrait y avoir une seule raison de changer de classe.

Donc, selon la cohésion et le principe de PRS, la classe devrait être bien ciblée et assumer une seule responsabilité.

Ici, dans votre cas, vous n'avez que 2 haricots mais à l'avenir, ces haricots pourraient augmenter. Alors, suivez votre deuxième point et créez une autre classe pour votre déclaration de haricot.

Et dans mon choix devrait même créer plus de classes de configuration, donc une classe de configuration devrait avoir un type similaire de beans.

14
Naresh Joshi

Oui, inclure vos beans dans la classe @Configuration est généralement la méthode préférée pour Spring.

C’est également l’un des moyens par lesquels Spring recommande d’injecter des inter-dépendances entre les haricots. L’exemple suivant est extrait du guide de référence de Spring here :

De plus, la portée par défaut de @Beans est SINGLETON. Si vous spécifiez une autre portée, telle que PROTOTYPE, l'appel sera transmis à la méthode d'origine. Consultez cette section dans le Guide de référence du ressort

6
Tomasz Kubiak

Cela dépend de choix personnels et il n'y a pas de bonne ou de mauvaise façon de le faire. Comme il est préférable ou indiqué dans la documentation des références Spring Boot.

Comme annotation de la classe principale avec @SpringBootApplication facilite le travail de Bootstrap application print.) Mais il ne recherche que les sous-paquetages. Ainsi, la configuration imbriquée dans le sous-dossier ne détectera pas le @Bean _ C'est automatiquement la seule chose à retenir, sauf qu'il s'agit de préférences personnelles.

1
Moshiour

Cela dépend de l'emplacement de la classe principale qui a généralement des annotations @SpringBootApplication. Vous pouvez annoter cette classe principale avec @ComponentScan(basePackageClasses = HelloWorld.class). Ici HelloWorld a eu des définitions annotées avec @Beans Et la classe est annotée avec @Configurations. Le conteneur Spring analysera tous les sous-packages de la classe spécifiée dans les arguments @ComponentScan. Vous pouvez également donner des caractères génériques pour l'argument basePackageClasses au lieu du nom de la classe, comme spécifié ci-dessus. Par exemple.

@SpringBootApplication
@ComponentScan(basePackageClasses = HelloWorld.class)
public class DemoApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
          SpringApplication.run(DemoApplication.class);
    }

}

Classe de haricot:

@Configuration
public class HelloWorld {

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

ne autre approche:

Généralement, dans les grands projets, nous aurons plusieurs classes de configuration Spring contenant des définitions de bean. Nous pouvons éviter de nous inquiéter du fait que toute la classe de beans devrait être dans le sous-paquet de la classe principale. Ce que nous pouvons faire, c’est que nous pouvons avoir une seule classe de configuration maître du ressort (mais assurez-vous que cette classe de configuration maître du ressort est sous-paquet de la classe principale afin que les annotations @SpringBootApplication Détectent automatiquement la configuration principale) et importez tous les éléments. les autres classes de haricots.

J'ai 2 classes de beans (TweetBeansConfig, TweetSystemHealthBeansConfig) dans le package com.ronak.Tweet (Ce package n'est pas un sous-package où la classe principale existe). J'ai une classe maître de configuration printanière (TweetMasterSpringConfig) et cette classe réside dans un paquet qui est un sous-paquetage où réside ma classe principale.

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

}
0
Ronak Jain

Cela dépend de l'emplacement de la classe principale qui a généralement des annotations @SpringBootApplication. Vous pouvez annoter cette classe principale avec @ComponentScan(basePackageClasses = HelloWorld.class). Ici, HelloWorld a des définitions de bean annotées avec @Beans Et la classe est annotée avec @Configurations.

Le conteneur Spring analysera tous les sous-packages de la classe spécifiée dans les arguments @ComponentScan. Vous pouvez également donner des entrées génériques au lieu du nom de la classe.

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

}
0
Ronak Jain