[JAVA] Je n'ai pas compris Spring Boot depuis un mois

introduction

Cela fait un mois que j'ai implémenté une application utilisant Spring Boot. Cependant, il y a encore beaucoup de parties que je ne comprends pas bien, je vais donc résumer ce que j'ai étudié ici comme un changement de note: v:

Qu'est-ce que DI (Dependency Injection)?

Un type d'IoC (Inversion of Control). Il semble y avoir ServiceLocator dans IoC, mais veuillez vous référer à ici.

DI est une abréviation pour Dependency Injection, qui est la base de tout Spring. L'explication simple de DI est *** Gestion des instances ***.

Qu'est-ce que la gestion des instances ...?

--Dans le conteneur DI, créez une nouvelle classe et créez une instance.

Qu'est-ce que l'injection de dépendances ...? Que fait DI?

Voir ici pour les significations de «dépendance» et «injection» dans DI. Si vous ne comprenez pas le mot «injection de dépendance», vous pouvez le changer en «injecter un objet». DI permet de faire facilement les deux choses ci-dessus en même temps, mais il y en a beaucoup d'autres. : pointer vers le bas:

Rechercher une classe gérée DI (analyse des composants)

Au démarrage de Spring, un processus appelé analyse des composants s'exécute et recherche une classe avec les annotations cibles suivantes gérées par DI. @Component @Controller @Service @Repository @Configuration @RestController @ControllerAdvice @ManagedBean @Named

Création et injection d'instances

Instanciez et injectez des beans enregistrés dans le conteneur DI. Après avoir collecté les classes cibles DI (Beans), DI crée (de nouvelles) ces instances. Ensuite, l'instance générée est injectée (affectée) par la méthode suivante.

Méthode d'injection

*** - Field injection (obsolète) ***

Pour l'injection de champ, une instance est injectée (assignée) simplement en ajoutant @ Autowired au champ (variable membre).

@Autowired
private SampleService sampleService;

Cependant, il a été déconseillé en raison des inconvénients suivants ...

  1. Vous ne pouvez pas vous moquer à moins d'utiliser un conteneur DI lors de la création du code de test.
  2. L'attribut final ne peut pas être ajouté au champ et il ne peut pas être immuable.

Alors maintenant, nous utilisons l'injection de constructeur suivante:

*** ・ Injection constructeur ***

@Service
@Transactional
public class SampleService {

  private final SampleRepository sampleRepository;

  // spring4.Après 3 quand il y a un constructeur@Le câblage automatique peut être omis
  @Autowired
  public SampleService(SampleRepository sampleRepository) {
    this.sampleRepository = sampleRepository;
  }

}

Pour une écriture plus facile, profitez de Lombok. Annotez simplement @ RequiredArgsConstructor à la classe: point_down:

@Service
@Transactional
@RequiredArgsConstructor
public class SampleService {

  private final SampleRepository sampleRepository;

}

Qu'est-ce qu'un haricot?

La classe gérée sur le conteneur DI est appelée "Bean". Fait référence à une classe avec l'annotation @ Component ou @ Controller, ou à une classe enregistrée dans le conteneur DI avec la méthode écrite comme @ Bean.

Comment mettre en œuvre DI

Comment implémenter JavaConfig DI

Tout d'abord, définissez le bean à enregistrer dans le conteneur DI.

JavaConfig.java


@Configuration
public class JavaConfig {
  @Bean
  public SampleComponent sampleComponent {
    return new SampleComponent();
  }
  @Baan
  public SampleController sampleService {
    return new SampleService();
  }
}

Maintenant, la valeur de retour du getter avec @ Bean est enregistrée comme Bean du conteneur DI. Dans JavaConfig, il est nécessaire de préparer des méthodes pour les instances gérées par des conteneurs DI. Cependant, vous pouvez définir les valeurs à transmettre au constructeur, etc. lors de la création d'une instance, et vous pouvez basculer la classe JavaConfig entre l'environnement de production et l'environnement de développement.

Implémentation DI basée sur les annotations

Sur une base d'annotations, Spring enregistre automatiquement les classes avec @ Component et @ Controller dans le conteneur DI.

Qu'est-ce que la gestion du cycle de vie des DI ...?

La gestion du cycle de vie est la gestion de la création (nouvelle) et de la destruction des instances. Lorsque vous utilisez un servlet pour créer une application Web, l'instance est enregistrée dans la portée Session ou Request, mais il est nécessaire de savoir exactement quand l'instance sera détruite.

Qu'est-ce qu'une portée ...?

L'étendue de la session et l'étendue de la demande sont les dates d'expiration de l'instance. Les dates d'expiration des deux portées sont différentes comme suit.

Portée de la session

La date d'expiration va de la connexion de l'utilisateur à la déconnexion. Par exemple, vous pouvez avoir des informations telles que si l'utilisateur est connecté en tant qu'étendue de session. Le code ci-dessous extrait le code que j'ai utilisé lorsque j'ai créé une application qui utilise OAuth.

OAuthDTO.java


@Data
@Component
@SessionScope
public class OAuthDTO {
  private boolean isLogin;
}

Demande de portée

Une requête HTTP expire. Par exemple, la plage allant de l'écran de connexion de l'utilisateur à la transition vers l'écran du profil de l'utilisateur en appuyant sur le bouton de connexion est la plage de l'étendue de la requête. Je l'ai utilisé dans l'Interceptor (https://qiita.com/kyabetsuda/items/78a61bfff859fbc9c63f), qui est traité avant l'appel du contrôleur.

OAuthInterceptor.java


@Component
@RequiredArgsConstructor
@RequestScope
public class OAuthInterceptor extends HandlerInterceptorAdapter {
  private final OAuthDTO oAuthDTO;

  /** {@inheritDoc} */
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws AuthenticationException {
    if (!oAuthDTO.isLogin()) {
      throw new AuthenticationException("Veuillez vous connecter.");
    }
    return true;
  }
}

Autres portées

*** ・ Singleton *** Créez une seule instance au démarrage de Spring. Après la création, une instance est partagée et utilisée. En raison du paramètre par défaut, si vous n'ajoutez pas l'annotation @ Scope, tout sera singleton.

*** · prototype *** Chaque fois que vous obtenez un bean, une instance est créée

*** ・ globalSession *** Des instances sont créées pour chaque session globale dans l'environnement de portlet. Il ne peut être utilisé que pour les applications Web prenant en charge les portlets.

*** ・ application *** Des instances sont créées pour chaque contexte du servlet.

Comme mentionné ci-dessus, vous pouvez facilement créer et détruire une instance en utilisant l'annotation @ Scope.

Choses à surveiller en DI

singleton Si vous n'ajoutez pas l'annotation @ Scope, l'instance sera créée avec singleton. Autrement dit, une seule instance de l'objet peut être créée. Si vous n'êtes pas conscient de la portée, cela peut provoquer des bogues.

Différence de portée

Par exemple, si une instance de portée singleton a un objet de portée session.

OAuthDTO.java


@Data
@Component
@SessionScope
public class OAuthDTO {
  private boolean isLogin;
}

OAuthService.java


@Service
@RequiredArgsConstructor
public class OAuthService {
 
   private final OAuthDTO oAuthDTO;

}

~~ Si cela se produit, le bean (OAuthDTO.java) avec la portée de session passera à la portée singleton. ~~

*** Ajouté le 28 avril *** Je suis désolé. Cette partie était fausse: arc:

@ SessionScope est disponible depuis le printemps 4.3 et était à l'origine @Scope(value = “session”, proxyMode = ScopedProxyMode.TARGET_CLASS) est. Ainsi, proxyMode = ScopedProxyMode.TARGET_CLASS est appelé *** Scoped Proxy ***, qui injecte le bean enveloppé dans Proxy, et lorsque vous appelez la méthode du bean injecté, il regarde en fait dans le conteneur DI. La méthode est déléguée au Bean téléchargé.

En d'autres termes ... Aucun changement de périmètre ne se produit. Actuellement, scoped-proxy permet de recevoir des choses avec une portée plus étroite que lui du conteneur DI sans se soucier du contrôleur ou de l'intercepteur.

Pour le prototype, etc., il est bon de se référer à ce qui suit.

Cependant, le code de l'exemple ci-dessus n'est pas correct. En injectant OAuthDTO.java dans OAuthService.java, la classe Service a un état. La classe Service n'est pas seulement appelée à partir de la *** classe Controller ***, donc si vous avez un état lié à un contexte spécifique tel qu'une requête HTTP avant la portée, il sera exécuté sur une route qui n'existe pas. Parfois, la question est de savoir où se procurer l'instance.

Par conséquent, dans le code de l'exemple ci-dessus, OAuthDTO.java doit être injecté dans la classe Controller.

Pour la méthode de mise en œuvre réelle, reportez-vous à ce qui suit.

Résumé du site auquel il est souvent fait référence ici

Annotation

Lombok

Points de révision du code

Recommended Posts

Je n'ai pas compris Spring Boot depuis un mois
Comment écrire un test unitaire pour Spring Boot 2
[Spring Boot] Comment créer un projet (pour les débutants)
J'ai écrit un test avec Spring Boot + JUnit 5 maintenant
Présentation de Spring Boot2, un framework Java pour le développement Web (pour les débutants)
Spring Boot pour l'apprentissage des annotations
J'ai créé un système d'exemple MVC simple à l'aide de Spring Boot
J'ai essayé le guide d'introduction de Spring Boot [Création d'un service Web RESTful]
Comment créer un hinadan pour un projet Spring Boot à l'aide de SPRING INITIALIZR
J'ai créé un formulaire de recherche simple avec Spring Boot + GitHub Search API.
Guide de démarrage de Spring Boot [Utilisation d'un service Web RESTful]
Une histoire que j'ai finalement comprise Java pour une déclaration en tant que non-ingénieur
Spring Boot pour la première fois
Annotations fréquentes pour les tests Spring Boot
Utiliser DBUnit pour le test Spring Boot
J'ai essayé GraphQL avec Spring Boot
Un mémo qui a touché Spring Boot
J'ai essayé Flyway avec Spring Boot
Créez un projet Spring Boot avec intellij et quittez immédiatement après le lancement
Je suis resté coincé en utilisant un cas de serpent pour le nom de variable dans Spring Boot
[Spring Boot] Je suis tombé sur un test du nombre d'appels de méthode (framework Spock)
[LINE BOT] J'ai créé un Ramen BOT avec Java (Maven) + Heroku + Spring Boot (1)
Qu'est-ce qu'un fichier .original Spring Boot?
Mémorandum WebMvcConfigurer de Spring Boot 2.0 (printemps 5)
J'ai essayé l'initialisation paresseuse avec Spring Boot 2.2.0
J'ai créé un plug-in pour IntelliJ IDEA
03. J'ai envoyé une demande de Spring Boot à l'API de recherche de code postal
J'ai essayé de cloner une application Web pleine de bugs avec Spring Boot