Cosa fa il framework Spring? Dovrei usarlo? Perché o perché no?


237

Quindi, sto iniziando un nuovissimo progetto in Java e sto pensando di usare Spring. Perché sto considerando la primavera? Perché molte persone mi dicono che dovrei usare Spring! Scherzi a parte, ogni volta che ho cercato di convincere le persone a spiegare cosa sia esattamente Spring o cosa faccia, non possono mai darmi una risposta diretta. Ho controllato le introduzioni sul sito SpringSource e sono o molto complicate o focalizzate sul tutorial, e nessuno di loro mi dà una buona idea del perché dovrei usarlo o di come mi semplificherà la vita. A volte la gente getta il termine "iniezione di dipendenza", che mi confonde ancora di più, perché penso di avere una diversa comprensione di cosa significhi quel termine.

Comunque, ecco un po 'del mio background e della mia app:

Sviluppo in Java da un po ', facendo sviluppo web back-end. Sì, faccio un sacco di test unitari. Per facilitare ciò, in genere realizzo (almeno) due versioni di un metodo: una che utilizza variabili di istanza e una che utilizza solo variabili passate al metodo. Quello che utilizza le variabili di istanza chiama l'altro, fornendo le variabili di istanza. Quando arriva il momento di unit test, uso Mockito per deridere gli oggetti e quindi effettuare chiamate al metodo che non utilizza le variabili di istanza. Questo è quello che ho sempre inteso essere "iniezione di dipendenza".

La mia app è piuttosto semplice, dal punto di vista CS. Piccolo progetto, 1-2 sviluppatori per cominciare. Principalmente operazioni di tipo CRUD con una serie di ricerche inserite. Fondamentalmente una serie di servizi Web RESTful, oltre a un front-end Web e infine ad alcuni client mobili. Sto pensando di fare il front-end in HTML / CSS / JS / JQuery, quindi non ho intenzione di usare JSP. Utilizzo di Hibernate come ORM e Jersey per implementare i servizi Web.

Ho già iniziato a scrivere codice e sono davvero impaziente di avere una demo là fuori che posso fare shopping e vedere se qualcuno vuole investire. Quindi ovviamente il tempo è essenziale. Capisco che Spring abbia abbastanza la curva di apprendimento, inoltre sembra che richieda un sacco di configurazioni XML, che in genere cerco di evitare come la peste. Ma se può semplificarmi la vita e (soprattutto) se può rendere più veloce lo sviluppo e i test, sono disposto a mordere il proiettile e imparare la primavera.

Quindi per favore. Educami Dovrei usare la primavera? Perché o perché no?


10
Penso che tu abbia davvero bisogno di provarlo per un po 'per vedere se ti piace e se è adatto per il tuo progetto. Personalmente lo odio.
Richard,

1
Mentre è possibile utilizzare XML o annotazioni; tieni presente che Spring prende una convenzione sulla mentalità di configurazione. Non è necessariamente una lista di oggetti che avete per affrontare.
Aaron McIver,

14
Mentre è vero che questa domanda è piuttosto ampia, penso che dovrebbe rimanere aperta. L'ho letto come "Quali vantaggi offre Spring per un progetto di medie dimensioni?", E questa è una buona domanda.
sleske,

1
Consiglio vivamente di leggere il mio libro tecnico preferito: Spring in Action, Third Edition di Craig Walls. È un'ottima lettura e cambierà il modo di programmare.
Alfredo,

4
Considerando Enterprise Java, è più facile rispondere a ciò che Spring non fa ...
m3th0dman

Risposte:


108

Cosa fa il framework Spring? Dovrei usarlo? Perché o perché no?

Spring è un framework che ti aiuta a "collegare" diversi componenti insieme. È molto utile nei casi in cui hai molti componenti e potresti decidere di combinarli in diversi modi o desiderare di sostituire facilmente un componente con un altro a seconda delle diverse impostazioni o ambienti.

Questo è quello che ho sempre inteso essere "iniezione di dipendenza".

Vorrei suggerire una definizione diversa:

"Progetta i tuoi oggetti in modo che facciano affidamento su una forza esterna per fornire loro ciò di cui hanno bisogno, con l'aspettativa che queste dipendenze vengano sempre iniettate prima che qualcuno chieda loro di iniziare a fare i loro soliti lavori."

Confrontalo con: "Ogni oggetto è responsabile per uscire e trovare tutto e tutti quelli di cui ha bisogno all'avvio."

sembra che richieda un sacco di configurazioni XML

Bene, la maggior parte delle cose XML (o basate su annotazioni) dicono cose di Spring come:

  • Quando qualcuno chiede "HammerStore", voglio che tu crei un'istanza di example.HammerStoree la restituisca. Memorizza l'istanza nella cache per la prossima volta, poiché deve esserci solo un negozio.
  • Quando qualcuno chiede "SomeHammer", voglio che tu ti chieda un "HammerStore" e restituisca il risultato del makeHammer()metodo del negozio . Do Non memorizzare nella cache questo risultato.
  • Quando qualcuno chiede "SomeWrench", voglio che tu crei un'istanza di example.WrenchImpl, Usa l'impostazione di configurazione gaugeAmounte mettila nella setWrenchSize()proprietà dell'istanza . Non memorizzare nella cache il risultato.
  • Quando qualcuno chiede "LocalPlumber", voglio che tu crei un'istanza di example.PlumberImpl. Inserire la stringa "Pedro" nel suo setName()metodo, inserire un "SomeHammer" nel suo setHammer()metodo e inserire un "SomeWrench" nel suo setWrench()metodo. Restituisci il risultato e memorizza nella cache il risultato per dopo poiché abbiamo bisogno di un solo idraulico.

In questo modo, Spring consente ai componenti di connessione, li etichetta, controlla i loro cicli di vita / memorizzazione nella cache e modifica il comportamento in base alla configurazione.

Per facilitare [i test] di solito realizzo (almeno) due versioni di un metodo: una che utilizza variabili di istanza e una che utilizza solo variabili che vengono passate al metodo.

Sembra un sacco di spese generali per non avere molti benefici per me. Invece, fai in modo che le variabili dell'istanza abbiano protectedo la visibilità del pacchetto e individua i test unitari all'interno dello stesso com.mycompany.whateverpacchetto. In questo modo è possibile ispezionare e modificare le variabili di istanza ogni volta che si desidera durante il test.


65

Innanzitutto, cos'è l'iniezione di dipendenza?

Semplice. Hai una classe, ha un campo privato (impostato su null) e dichiari un setter pubblico che fornisce il valore per quel campo. In altre parole, la dipendenza della classe (il campo) viene iniettata da una classe esterna (tramite il setter). Questo è tutto. Niente di magico.

In secondo luogo, Spring può essere utilizzato senza XML (o molto poco)

Se ti immergi con Spring 3.0.5.GA o superiore, puoi utilizzare il supporto per l'iniezione delle dipendenze da JDK6 +. Ciò significa che è possibile collegare le dipendenze utilizzando le annotazioni @Componente @Resource.

Perché usare la primavera?

Ovviamente, l'iniezione di dipendenza promuove test di unità molto facili poiché tutte le tue classi hanno setter per le dipendenze importanti e queste possono essere facilmente derise usando il tuo framework di derisione preferito per fornire il comportamento richiesto.

A parte questo, Spring fornisce anche molti modelli che fungono da classi base per rendere l'utilizzo delle tecnologie standard JEE un gioco da ragazzi con cui lavorare. Ad esempio, JdbcTemplate funziona bene con JDBC, JpaTemplate fa cose buone con JPA, JmsTemplate rende JMS piuttosto semplice. RestTemplate è semplicemente fantastico nella sua semplicità. Per esempio:

RestTemplate restTemplate = new RestTemplate();
MyJaxbObject o = restTemplate.getForObject("https://secure.example.org/results/{param1}?param2={param2}",MyJaxbObject.class,"1","2");

e hai finito. I parametri vengono iniettati e devi solo fornire le annotazioni JAXB per MyJaxbObject. Ciò non dovrebbe richiedere tempo se li hai generati automaticamente da un XSD utilizzando il plug-in MAX JAXB. Si noti che non vi era alcun casting in corso, né era necessario dichiarare un marshaller. È tutto fatto per te.

Potrei rimanere per sempre sulle meraviglie di Spring, ma forse la cosa migliore da fare è provare un semplice picco di codice in cui si tenta di collegare un servizio Web RESTful per pompare i dati da un DAO iniettato che supporta le transazioni.


4
Sì, RestTemplate è davvero fantastico. Ho circa 100 righe di codice che posso eliminare e sostituire con 2-3 righe.
Kevin,

11
A nitpick: Dependency Injection include anche l'approccio basato sul costruttore. Non devi necessariamente avere setter.
Darien,

28

Prima di tutto, la tua comprensione dell'iniezione di dipendenza non è fondamentalmente sbagliata, ma abbastanza diversa da ciò che la maggior parte delle persone intende quando usano il termine. Quello che descrivi è un modo piuttosto strano e non convenzionale per raggiungere la testabilità. Ti consiglierei di allontanartene, poiché altri sviluppatori saranno piuttosto perplessi da quel tipo di codice.

L'iniezione di dipendenze come generalmente intesa (e implementata da Spring) significa che le dipendenze di una classe (ad es. Un'origine dati JDBC) non vengono recuperate dalla classe stessa, ma "iniettate" da un contenitore quando viene creata l'istanza. Quindi non hai due versioni di ogni metodo che utilizza l'origine dati; invece, si ha una configurazione di iniezione di dipendenza in cui viene iniettata l'origine dati "reale" e una in cui viene iniettato un mock. Oppure, se l'iniezione avviene tramite il costruttore o un getter, il codice di test può eseguire l'iniezione in modo esplicito.

In secondo luogo, Spring non è solo un'iniezione di dipendenza, sebbene questa sia la sua funzionalità principale. Fornisce inoltre transazioni dichiarative, pianificazione dei lavori, autenticazione e un sacco di altre funzionalità (incluso un framework Web MVC completo) di cui potresti aver bisogno. Esistono altri framework che offrono le stesse funzionalità, ma a parte Spring, solo Java EE li ha tutti integrati.


OP comprende DI perfettamente perfettamente
Basilevs,

19

Perché vuoi usare Spring, puoi leggerlo su http://www.wrox.com/WileyCDA/Section/Why-Use-the-Spring-Framework-.id-130098.html

In sintesi :

  • Le applicazioni J2EE tendono a contenere quantità eccessive di codice "idraulico". Molte revisioni del codice rivelano ripetutamente un'alta percentuale di codice che non fa nulla: codice di ricerca JNDI, Trasferisci oggetti, tenta / cattura blocchi per acquisire e rilasciare risorse JDBC. . . . La scrittura e la manutenzione di tale codice idraulico dimostrano un grosso consumo di risorse che dovrebbero essere focalizzate sul dominio aziendale dell'applicazione.

  • Molte applicazioni J2EE utilizzano un modello a oggetti distribuiti laddove ciò sia inappropriato. Questa è una delle principali cause di eccessiva duplicazione di codice e codice. È anche concettualmente sbagliato in molti casi; le applicazioni distribuite internamente sono più complesse delle applicazioni localizzate e spesso molto meno performanti. Naturalmente, se i requisiti aziendali dettano un'architettura distribuita, è necessario implementare un'architettura distribuita e accettare il compromesso che ne deriva (e Spring offre funzionalità che aiutano in tali scenari). Ma non dovresti farlo senza un motivo convincente.

  • Il modello del componente EJB è eccessivamente complesso. EJB è stato concepito come un modo per ridurre la complessità durante l'implementazione della logica di business nelle applicazioni J2EE; nella pratica non è riuscito a raggiungere questo obiettivo.

  • EJB è abusato. EJB è stato progettato essenzialmente per applicazioni transazionali distribuite internamente. Mentre quasi tutte le applicazioni non banali sono transazionali, la distribuzione non dovrebbe essere integrata nel modello di componente di base.

  • Molti "modelli di progettazione J2EE" non sono, in realtà, modelli di progettazione, ma soluzioni alternative per i limiti tecnologici. L'uso eccessivo della distribuzione e l'uso di API complesse come EJB hanno generato molti modelli di progettazione discutibili; è importante esaminarli criticamente e cercare approcci più semplici, più produttivi.

  • Le applicazioni J2EE sono difficili da testare. Le API J2EE, e in particolare il modello di componente EJB, sono state definite prima che il movimento agile decollasse. Pertanto, il loro design non tiene conto della facilità di test unitari. Tramite entrambe le API e i contratti impliciti, è sorprendentemente difficile testare le applicazioni basate su EJB e molte altre API J2EE al di fuori di un server delle applicazioni. Tuttavia, i test unitari all'esterno di un server applicazioni sono essenziali per ottenere un'elevata copertura dei test e riprodurre molti scenari di errore, come la perdita di connettività a un database. È inoltre essenziale garantire che i test possano essere eseguiti rapidamente durante il processo di sviluppo o manutenzione, riducendo al minimo i tempi improduttivi in ​​attesa di ridistribuzione.

  • Alcune tecnologie J2EE hanno semplicemente fallito. L'offensore principale qui sono i bean di entità, che si sono rivelati poco disastrosi per la produttività e per i loro vincoli sull'orientamento degli oggetti.


13

In passato abbiamo scritto applicazioni e servizi Web semplici, efficienti e veloci utilizzando solo core Java, Servlet e JSP, html e xml, API JDBC. Era abbastanza buono; JUnit è stato un buon strumento per testare. Siamo stati tranquilli che il nostro codice ha funzionato.

Hibernate è venuto per semplificare SQL e abilitare la vera mappatura delle tabelle del database con oggetti Java, consentendo alle relazioni gerarchiche di riflettersi nella mappatura delle relazioni di oggetti o ORM come la chiamiamo. Lo amavo. Soprattutto non abbiamo dovuto mappare il ResultSet in un oggetto Java o in un tipo di dati.

Sono arrivati ​​Struts per aggiungere il modello Controller vista modello alle nostre app Web, è stato bello.

Gli EJB erano un enorme sovraccarico e il dolore e le annotazioni facevano apparire il codice come un graffio di pollo e ora la primavera è saltata addosso a noi innocenti. Mi sembra esagerare.

Ad esempio, ora impacchettiamo il nostro semplice URL jdbc, utente, prima passiamo a jdbc.properties, poi in secondo luogo alle proprietà di ibernazione e poi a Spring bean per la terza volta!

A parte questo, prendi in considerazione la possibilità di ottenere una connessione dove ti serve è davvero semplice come mostrato di seguito in puro Java, che è quello che stiamo facendo dopo aver attraversato tutta quella roba di aria calda con Spring:

Connection connection = DriverManager.getConnection(url, user, pass);

Questo è di per sé autoesplicativo sul fatto che si tratta di un grande giro e si avvolge continuamente per fare una cosa semplice veloce e facile senza altri grandi benefici. È come avvolgere tonnellate e tonnellate di carta regalo attorno a un piccolo regalo carino che è tutto ciò che tieni davvero comunque.

Un altro esempio è un aggiornamento batch. Con Spring è complicato coinvolgendo alcune classi e interfacce prima di poter utilizzare JdbcTemplate per eseguire un aggiornamento batch. Con jdbc semplice è semplicemente:

Statement statement = connection.createStatement();
statement.addBatch(sqlquery);
statement.executeBatch();

Non può essere più semplice o più veloce di così.

Non appoggio questo framework. Scusate. Chi diavolo vuole iniezioni ogni volta che hanno bisogno di qualcosa?


6
quel codice è semplice, ma dove è definita la gestione della tua transazione e come la collaudi? Entrambe le cose sono rese più semplici entro la primavera. Inoltre, il tuo codice java è direttamente collegato a una connessione db, a meno che non memorizzi gli URL di connessione e le password esternamente, questo è reso più semplice entro la primavera.
NimChimpsky,

+1 per questa risposta, per rispondere al commento sopra, man usa i tuoi modelli di design leggeri (GOF), singleton per il pool di connessioni, una classe proxy che fornisce sql (stringa) e valori (array) all'oggetto Database (quale metodo , dipende dal metodo http), il dbobject gestisce il pool di connessioni, le transazioni ecc. eseguendo la query seguita dal rilascio. Un oggetto utilizzabile in tutti i moduli, nessuno necessita di un eccessivo codice della piastra della caldaia. punto bonus con impostazione test unitari su classe proxy e dbobject.
user2727195

Dai un'occhiata a Spring-Data-JPA! Annota un pojo in un'entità, implementa un'interfaccia e definisci le firme dei metodi usando nomi ragionevoli, come findHammerByWeight () e spring implementa i metodi per te, offrendoti un repository iniettabile che puoi utilizzare in tutti gli altri servizi aziendali o classi di controller .
mancini0

13

Cosa fa il framework Spring?

La primavera è come oggi non solo, ciò che era noto come un semplice framework, è un ecosistema completo.

Temi trattati dall'ecosistema di primavera:

  • Spring Framework (es. Dependency Injection, AOP ...)

  • Spring Cloud

  • Dati di primavera

  • Spring Security

  • Lotto di primavera

  • Primavera sociale

Vedi qui per la copertura completa dell'ecosistema. È possibile selezionare i progetti in modo da poter utilizzare Google Guice per DI e, ad esempio, Spring Security per gestire le questioni relative alla sicurezza. Non è necessario acquistare l'intero ecosistema.

Lo stesso quadro di primavera copre oggi principalmente

  • Iniezione di dipendenza

  • Programmazione orientata agli aspetti inclusa la gestione delle transazioni dichiarativa di Spring

  • Applicazione web Spring MVC e framework di servizi Web RESTful

  • Supporto di base per JDBC, JPA, JMS

Fonte spring.io

In generale, si potrebbe dire che Spring è una raccolta di modelli e pratiche implementati nel codice, che potrebbero aiutare a migliorare o accelerare il ciclo di sviluppo delle applicazioni.

Per cosa (il core-framework) è più noto per le sue capacità nel campo dell'iniezione di dipendenza . La stessa primavera ha, quello che viene chiamato inversione del contenitore di controllo o contenitore IoC corto o anche il contenitore più corto (per il quale a volte si usa anche "molla").

Che cos'è l'iniezione di dipendenza?

Iniezione di dipendenza significa che il tuo oggetto riceve ogni dipendenza da altri oggetti tramite un meccanismo esternalizzato.

Supponiamo che tu abbia una macchina, nel modo tipico, è implementata è:

public class Car {

    Engine e;

    public Car() { 
        e = new Engine(); 
    }

}

L'oggetto auto dipende da un motore. Poiché il motore è implementato come membro di un'auto, non può essere sostituito per esempio con un motore di prova.

Ora entra in gioco l' iniezione di dipendenza :

public class Car {

    Engine e;

    public Car(Engine e) { 
        this.e = e; 
    }

}

Dopodiché, sei in grado di cambiare motore. Quello che vedi sopra è chiamato iniezione del costruttore . Esistono altri tipi come ad esempio setter -injection o method -injection. In che modo ti aiuta Spring? Spring consente di contrassegnare i componenti da iniettare con l'annotazione @Autowireded esegue automaticamente il cablaggio dell'oggetto iniettato: è probabile che il componente che si desidera iniettare abbia dipendenze. Gli iniettabili - per così dire - sono contrassegnati da@Component

public class Car {

    Engine e;

    @Autowired
    public Car(Engine e) { 
        this.e = e; 
    }

}

Ma questa è solo una delle tante funzionalità che Spring ha da offrire.

Dovrei usare la primavera? Perché o perché no?

Poiché la primavera non è molto invadente e offre molti aiuti, dovresti prendere in considerazione l'uso della primavera. Soprattutto per i nuovi progetti, Spring Boot è molto interessante. start.spring.io offre un'interfaccia point'n'click facile da usare per generare un modello di progetto per iniziare. È anche possibile utilizzare curlper recuperare un modello:

curl start.spring.io

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

:: Spring Initializr ::  https://start.spring.io

This service generates quickstart projects that can be easily customized.
Possible customizations include a project's dependencies, Java version, and
build system or build structure. See below for further details.

The services uses a HAL based hypermedia format to expose a set of resources
to interact with. If you access this root resource requesting application/json
as media type the response will contain the following links:
+-----------------+-----------------------------------------+
| Rel             | Description                             |
+-----------------+-----------------------------------------+
| gradle-build    | Generate a Gradle build file            |
| gradle-project  | Generate a Gradle based project archive |
| maven-build     | Generate a Maven pom.xml                |
| maven-project * | Generate a Maven based project archive  |
+-----------------+-----------------------------------------+

...

D'altra parte, framework come spark o dropwizard offrono un buon punto di partenza anche per la creazione rapida di app Web.


1
Risposta molto istruttiva!
GOXR3PLUS

D'accordo, ottima risposta. OP, simpatizzo con te. Ho anche avuto diverse persone che mi mostrano dimostrazioni di primavera in cui "semplificano" il codice aggiungendo un file XML e 2 livelli di riferimento indiretto solo per poter chiamare il costruttore in una classe :) Devi solo tuffarti o andare a un presentazione davvero buona e alla fine diventerà chiaro dove sono i vantaggi e gli svantaggi
Adam Hughes,

4

È un framework scritto in Java con molte cose incluse per rendere funzionale la tua applicazione web (es. Supporto per l'internazionalizzazione). Fornisce inoltre un buon modo per strutturare l'applicazione in livelli. Usalo, ti farà risparmiare molto tempo a lungo termine.

Un buon libro per conoscere Spring è: Expert Spring MVC e Web Flow

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.