Printemps: confusion sur le bon chemin d'apprentissage


Ces derniers jours, j'ai moi-même appris Spring Boot et créé un serveur et un client de service Web REST, puis ajouté une authentification de base et déployé en tant que package autonome et war. Je l'ai fait en incorporant spring-boot-starter-web, spring-boot-starter-test, spring-boot-starter, spring-boot-starter-security, spring-boot-starter-tomcat, spring-web, jackson-databind dans mon projet gradle et copie hten modification via divers sites Web.

Après avoir été confus par la multitude de sites Web faisant les choses de manière complètement différente (complètement différente annotations, une certaine utilisation de fichiers de configuration) cela a fonctionné et je l'ai ensuite modifié à l'aide d'un intercepteur/convertisseur de message, d'en-têtes bruts, puis via un générateur de modèle rest.

Cependant, j'ai l'impression que je n'ai vraiment aucune idée de comment ou pourquoi cela a fonctionné, même si j'ai écrit un peu de code pour que tout fonctionne, y compris l'authentification de base, de 4 manières différentes. Cela a fonctionné comme par magie, et je ne l'aime pas: par exemple, si je voulais ajouter plus de choses qui n'étaient pas basées sur "boot", comment ferais-je ou que font toutes les annotations et pourquoi sont-elles requises, par exemple @SpringBootApplication, @Configuration, ou pourquoi certaines classes @Bean et d'autres non).

Pour résumer, spring est un framework massif (le site Web répertoriant les paquets prend en charge une page par lui-même), devrais-je vraiment apprendre spring core/framework avant toute autre chose, puis peut-être spring MVC ou spring web services avant d'apprendre boot?

Je peux trouver de nombreuses ressources pour m'apprendre les différents paquets, mais aucune me dit pourquoi ils travaillent ou par où commencer vraiment et spécifiquement rien ne me dira comment les paquets s'interconnectent. C'est assez accablant.

Je m'attends à ce que cela soit fermé car non constructif, mais cela semblait être le meilleur endroit pour obtenir une réponse au printemps.

Author: M. Deinum, 2017-01-16

2 answers

Une très courte histoire du printemps

Commençons par une petite leçon d'histoire... L'année est 2002 et la plupart des développeurs Java ont travaillé dans l'espace J2EE et beaucoup d'entre eux n'étaient pas heureux. L'un d'eux était Rod Johnson qui a écrit un livre intitulé Expert One-on-One J2EE Design and Development et c'était comment on pouvait développer une application d'entreprise sans EJBs et de meilleure façon. Le code de ce livre est devenu le fondement du cadre de printemps.

Configuration du ressort

Jetons un coup d'œil à une classe Java simple.

@Component("hello")
public class HelloWorld {

    private String name = "World!";

    public void setName(String name) {
        this.name=name;
    }

    public void sayHello() {
        System.out.println("Hello, " + name);
    }
}

Fichiers de propriétés de configuration Spring

Au début, la seule option de configuration était d'utiliser un fichier de propriétés. Nommons ce fichier application-context.properties. Pour créer une instance de la classe java ci-dessus et définir un nom, le contenu suivant dans le application-context.properties était nécessaire.

hello.(class)=biz.deinum.samples.configurations.HelloWorld
hello.name=Marten!

Le (class) était une propriété spéciale (il y a plus comme (scope) et (abstract) voir lejavadoc pour plus d'options. Cela indiquerait quelle classe devait être chargée. Pour utiliser le fichier de propriétés, il faudrait créer un PropertiesBeanDefinitionReader passer d'un BeanFactory. (Qui à son tour peut être passé à un ApplicationContext si vous avez besoin de fonctionnalités sophistiquées comme AOP)

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("classpath:application-context.properties");

HelloWorld helloWorld = beanFactory.getBean("hello", HelloWorld.class);
helloWorld.sayHello();

Cependant, cette configuration basée sur les propriétés était un peu limitative et XML convenait au monde. D'où les premiers pas dans la configuration XML où né.

Configuration Spring - Fichiers XML (partie 1)

Pour représenter la même configuration avec XML ce qui suit serait nécessaire.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="hello" class="biz.deinum.samples.configurations.HelloWorld">
        <property name="name" value="Marten!" />
    </bean>

</beans>

Une fois chargé, cela créerait une instance de HelloWorld avec les mêmes paramètres que le fichier de propriétés. Le chargement nécessiterait un XmlBeanDefinitionReader.

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("classpath:/applicationContext-basic.xml");

HelloWorld helloWorld = beanFactory.getBean("hello", HelloWorld.class);
helloWorld.sayHello();

Configuration Spring - Fichiers XML (partie 2)

XML est assez verbeux mais lisible. Mais configurer des choses comme AOP (Transactions par exemple),MVC etc. sont tout à fait travail certains. (Ou des choses comme la sécurité voir ce pour le prédécesseur du printemps La sécurité sans un espace de noms). Ainsi, le XML nouveau et amélioré avait la notion d'espaces de noms permettant des choses comme <tx:annotation-driven /> <aop:config /> etc.

Configuration de ressort-Annotation conduite

L'étape suivante a été l'introduction de Java5, qui permettait les annotations. Comme toute la communauté Java a demandé une configuration basée sur les annotations, cela a été ajouté. D'où l'introduction de @Component, @Autowired et l'aime.

Ajouter @Component à la classe HelloWorld et utiliser l'espace de noms pour activer le composant l'analyse réduit la quantité de XML que l'on doit écrire.

En supposant que @Component("hello") est sur la classe HelloWorld, le XML suivant est nécessaire.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="biz.deinum.samples.configurations" />

</beans>

Pour charger cette configuration, il suffit de changer l'emplacement du fichier à charger.

Configuration Spring - Java Config

Puis tout d'un coup, l'amour pour XML était terminé et les gens voulaient utiliser un langage qu'ils connaissent et ce langage est Java. D'où la naissance de la configuration basée sur Java.

@Configuration
public class HelloWorldConfiguration {

    @Bean
    public HelloWorld hello() {
        HelloWorld helloWorld = new HelloWorld();
        helloWorld.setName("Marten!");
        return helloWorld;
    }
}

Le @Bean l'annotation est une indication que cette méthode produit un bean et est traitée en utilisant ASM avant d'être réellement chargée par Spring. Cependant, le traitement de configuration Java est assez complexe et ne fonctionne qu'avec un ApplicationContext. Vous pouvez soit ajouter la classe @Configuration à un fichier XML et la charger pour qu'elle soit traitée, soit utiliser un AnnotationConfigApplicationContext spécialisé pour la charger (ou la détecter).

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(HelloWorldConfiguration.class);
context.getBean("hello", HelloWorld.class).sayHello();

En XML, nous avons des espaces de noms pour faciliter la configuration. Dans Java Config land, nous avons les différentes annotations @Enable* comme @EnableTransactionManagement ce qui est le même que <tx:annotation-driven /> en XML.

Pensées / Suggestions

Quelle option de configuration utiliser, si vous êtes nouveau, je suggère de commencer par la configuration basée sur Java, bien que XML soit probablement un peu plus facile à comprendre (À mon humble avis). Toutes les options de configuration fonctionnent encore aujourd'hui, vous pouvez même les mélanger et les assortir si nécessaire.

Pour Spring, peu importe, ce qui compte pour Spring, ce sont les BeanDefinition s dont la source est utilisée pour les construire (propriétés, configuration xml ou java) n'a pas d'importance.

Botte à ressort

Jusqu'à présent, la seule chose couverte est le printemps lui-même. Aucun autre projet n'a été touché (bien qu'il ait été mentionné). Mais comme vous pouvez l'imaginer, le temps passe et à mesure que les configurations et la complexité des applications augmentent, nous voulions plus de convention que de configuration. L'une des raisons pour lesquelles Spring Boot a vu le jour.

Marquer une classe avec @SpringBootApplication rend cette classe a @Configuration, permettra l'analyse des composants (à partir de la même package la classe annotée est dans) et activera la configuration automatique.

@SpringBootApplication
public class HelloApplication {

    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(HelloApplication.class, args);

        BeanFactoryHelper.sayHello(context);
        BeanFactoryHelper.statistics(context);
    }

    @Bean
    public HelloWorld hello() {

        HelloWorld hello = new HelloWorld();
        hello.setName("Marten!");
        return hello;
    }
}

Cette classe va lancer l'application, dire bonjour, imprimer des informations sur le contexte et se terminer. Sans que vous ne créiez vous-même un contexte d'application ou une usine.

Pourquoi la méthode @Bean eh bien la classe HelloWorld est dans un paquet non couvert par l'analyse des composants par défaut de Spring Boot et nous devons donc déclarer le bean. Nous pouvons le faire dans la classe HelloApplication car c'est aussi un @Configuration (dû à cela étant une méta annotation sur @SpringBootApplication).

Maintenant, si vous remplacez @SpringBootApplication par @SpringBootApplication(scanBasePackageClasses = HelloWorld.class), vous pouvez supprimer l'annotation @Bean car le HelloWorld serait maintenant détecté par l'analyse des composants (activé par la méta annotation @ComponentScan sur @SpringBootApplication).

Le code de cette réponse peut être trouvé ici.

 7
Author: M. Deinum, 2017-01-17 11:51:04

Spring framework il s'agit d'injection de dépendance et il est utilisé pour les services Web REST, mais cela ne signifie pas que vous ne pouvez pas avoir Spring dans une application de base.

Pour résumer, spring est un framework massif (le site Web répertoriant les paquets prend en charge une page par lui-même), devrais-je vraiment apprendre spring core/framework avant toute autre chose, puis peut-être spring MVC ou spring web services avant d'apprendre boot?

Vous devriez apprendre comment le printemps fonctionne dans général et comment fonctionnent les instanciations. Fondamentalement, il fait une recherche dans votre projet et l'instanciation de chaque classe annotée avec @Component (@Service, @RestController, @Controller ... et ainsi de suite). Lorsque vous @Autowire, une référence est transmise à votre variable.

Après avoir été confus par la multitude de sites Web faisant les choses de manière complètement différente (annotations complètement différentes, utilisation de fichiers de configuration), cela a fonctionné et je l'ai ensuite modifié en utilisant un intercepteur / convertisseur de messages, des en-têtes bruts et ensuite, via un générateur de modèle rest.

La plupart des exemples que vous pouvez trouver sur Internet de plus de 1 à 2 ans sont probablement obsolètes(mais pas toujours). Lorsque vous recherchez quelque chose, gardez cela à l'esprit. C'est la principale cause pour laquelle il y a tant d'implémentations.

Je peux trouver de nombreuses ressources pour m'apprendre les différents paquets, mais aucune ne me dit pourquoi ils fonctionnent ou par où commencer vraiment et plus précisément rien ne me dira comment les paquets s'interconnectent. C'est assez écrasante.

C'est écrasant. C'est un grand framework avec un grand domaine d'applicabilité. Meilleur endroit pour apprendre comment les choses fonctionnent est: https://spring.io/docs/reference

 2
Author: Alexandru Hodis, 2017-01-16 19:53:29