Programmering

Hvad er forår? Komponentbaseret udvikling til Java

Foråret er måske det bedste af de komponentbaserede rammer, der opstod ved begyndelsen af ​​det 21. århundrede. Det forbedrer markant den måde, som udviklere skriver og leverer infrastrukturkode på Java-baserede applikationer. Siden starten er Spring blevet anerkendt som en førende ramme for virksomhedens Java-udvikling. Som en end-to-end applikationsramme spejler Spring nogle af Java EE-funktionerne, men det tilbyder en kombination af funktioner og programmeringskonventioner, som du ikke finder andre steder.

Denne artikel introducerer Spring og dets kerneprogrammeringsfilosofi og metodologi: Inversion af kontrol og afhængighedsinjektion. Du kommer også i gang med forårskommentarer og et par praktiske kodningseksempler.

Afhængighedsindsprøjtning og inversion af kontrol

Forårs kerneidee er, at du i stedet for selv at styre objektrelationer aflaster dem til rammen. Inversion of control (IOC) er den metode, der bruges til at styre objektrelationer. Afhængighedsindsprøjtning er mekanismen til implementering af IOC. Da disse to koncepter er beslægtede, men forskellige, lad os overveje dem nærmere:

  • Inversion af kontrol (IOC) gør netop, hvad navnet siger: det inverterer det traditionelle hierarki af kontrol for at opfylde objektrelationer. I stedet for at stole på applikationskode for at definere, hvordan objekter relaterer til hinanden, defineres relationer af rammen. Som metode introducerer IOC konsistens og forudsigelighed for at imødegå relationer, men det kræver, at du som udvikler opgiver en vis finkornet kontrol.
  • Afhængighedsinjektion (DI) er en mekanisme, hvor rammen "injicerer" afhængigheder i din app. Det er den praktiske implementering af IOC. Afhængighedsinjektion hænger på polymorfisme i den forstand, at det gør det muligt at ændre opfyldelsen af ​​en referencetype baseret på konfigurationer i rammen. Rammen indsprøjter variable referencer i stedet for at få dem udført manuelt i applikationskode.

JSR-330

Ligesom meget i Java-verdenen, hvad der begyndte som en in-the-wild innovation, Spring, er delvist blevet absorberet af standardspecifikationer. I dette tilfælde er JSR-330 Java-standarden. Det pæne ved JSR-330 spec er, at du kan bruge det andre steder og se det i brug andre steder ud over foråret. Du kan bruge det uden at bruge Spring. Forår bringer dog meget mere til bordet.

Eksempel nr. 1: Fjederafhængighedsinjektion

Inversion af kontrol og afhængighedsinjektion forstås bedst ved at bruge dem, så vi starter med et hurtigt programmeringseksempel.

Sig, du modellerer en bil. Hvis du modellerer i almindelig gammel Java, har du muligvis et interface-medlem på Bil klasse til reference en Motor interface, som vist i liste 1.

Notering 1. Objektrelationer i almindelig gammel Java

 public Interface Engine () {...} public class Car {private Engine engine; public Engine getEngine () {...} public void setEngine (Engine engine) {...}} 

Liste 1 indeholder en grænseflade til en Motor type og en klasse for betonen Bil type, der refererer til Motor. (Bemærk, at i et rigtigt programmeringsscenarie vil disse være i separate filer.) Når du opretter en Bil For eksempel vil du indstille tilknytningen som vist i liste 2.

Fortegnelse 2. Oprettelse af en bil med motorgrænsefladen

 // ... Bil newCar = ny bil (); Motor sixCylEngine = ny InlineSixCylinderEngine (); newCar.setEngine (sixCylEngine); // Gør ting med bilen 

Bemærk, at du opretter Bil objekt først. Du opretter derefter et nyt objekt, der opfylder Motor interface, og tildel det manuelt til Bil objekt. Sådan fungerer objektforeninger i almindelig gammel Java.

Modelleringskurser og genstande om foråret

Lad os nu se på det samme eksempel i foråret. Her kan du gøre noget som det, der vises i Listing 3. Du starter med Bil klasse, men i dette tilfælde tilføjer du en kommentar til den: @Indsprøjte.

Liste 3. Eksempel på brug af @Inject-kommentaren om foråret

 offentlig klasse bil {@Inject privat motor motor; // ...} 

Bruger @Indsprøjte kommentar (eller @Autowired, hvis du foretrækker) beder Spring om at søge i konteksten og automatisk injicere et objekt i referencen, baseret på et sæt regler.

Overvej derefter @Komponent kommentar, vist i liste 4.

Listing 4. @Komponentkommentar

 @Komponent offentlig klasse InlineSixCylinderEngine implementerer motor {// ...} 

Annotering af en klasse med @Komponent fortæller foråret, at det er tilgængeligt til at udføre injektioner. I dette tilfælde er InlineSixCylEngine ville blive injiceret, fordi den er tilgængelig og opfylder foreningens interface-krav. Om foråret kaldes dette en "autowired" injektion. (Se nedenfor for mere om Spring's @Autowired kommentar.)

Afkobling som designprincip

Inversion af kontrol med afhængighedsinjektion fjerner en kilde til konkret afhængighed fra din kode. Ingen steder i programmet er der en hardkodet henvisning til Motor implementering. Dette er et eksempel på afkobling som et software design princip. Afkobling af applikationskode fra implementering gør din kode lettere at administrere og vedligeholde. Applikationen ved mindre om, hvordan dens dele passer sammen, men det er meget lettere at foretage ændringer på ethvert tidspunkt i applikationens livscyklus.

@Autowired vs @Inject

@Autowired og @Indsprøjte gør det samme. Imidlertid, @Indsprøjte er Java-standardkommentar, hvorimod @Autowired er specifik for foråret. De tjener begge det samme formål med at fortælle DI-motoren at indsprøjte feltet eller metoden med et matchende objekt. Du kan bruge en af ​​dem om foråret.

Oversigt over forårets rammer

Nu hvor du har set noget forårskode, lad os tage et overblik over rammen og dens komponenter. Som du kan se, består rammen af ​​fire hovedmoduler, der er opdelt i pakker. Spring giver dig en hel del fleksibilitet med de moduler, du bruger.

  • Kernebeholder
    • Kerne
    • Bønne
    • Sammenhæng
    • Udtrykssprog
  • Aspektorienteret programmering (AOP)
    • AOP
    • Aspekter
    • Instrumentering
  • Dataadgang og integration
    • JDBC
    • JPA / ORM
    • JMS
    • Transaktioner
  • Internettet
    • Web / REST
    • Servlet
    • Struts

I stedet for at dække alt her, lad os komme i gang med to af de mere almindeligt anvendte Spring-funktioner.

Start af et nyt projekt: Spring Boot

Vi bruger Spring Boot til at oprette et eksempel på et projekt, som vi bruger til at demonstrere Spring-funktioner. Spring Boot gør det meget lettere at starte nye projekter, som du selv vil se. For at begynde skal du kigge på hovedklassen vist nedenfor. I Spring Boot kan vi tage en hovedklasse med en hoved () metode, og vælg derefter at køre den enkeltstående eller pakke til implementering i en container som Tomcat.

Fortegnelse 5 har konturerne af vores hovedklasse, som lever efter standarden src / main / java / hej Beliggenhed.

Liste 5. Hovedklasse med Spring Boot

 pakke hej; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application {public static void main (String [] args) {SpringApplication.run (Application.class, args); }} 

Bemærk to ting om ovenstående kode: For det første er alt arbejdet abstraheret i rammen. Hovedklassen starter appen, men den ved ikke noget om, hvordan appen fungerer eller leverer dens funktionalitet. For det andet, den SpringApplication.run () gør det egentlige job med at starte appen og videresende den Ansøgning klasse selv. Igen er det arbejde, som appen udfører, ikke tydeligt her.

Det @SpringBootApplication annotation afslutter et par standardanmærkninger og beder Spring om at se på pakken, hvor hovedklassen findes for komponenter. I vores tidligere eksempel, med bilen og motoren, ville dette give Spring mulighed for at finde alle klasser, der er kommenteret med @Komponent og @Indsprøjte. Selve processen kaldes komponentscanning, kan tilpasses meget.

Du kan oprette appen med standarden mvn ren installation, og du kan køre det med Spring Boot-målet (mvn spring-boot: løb). Før vi gør det, lad os se på denne applikations pom.xml fil.

Fortegnelse 6. Starter pom.xml

 com.javaworld what-is-spring 1.0.0 org.springframework.boot spring-boot-starter-parent 2.1.3.RELEASE 1.8 org.springframework.boot spring-boot-maven-plugin 

Bemærk to vigtige funktioner i ovenstående kode:

  1. Det forælder element er afhængig af spring-boot-starter-parent projekt. Dette overordnede projekt definerer et antal nyttige standardindstillinger, f.eks. Standard compiler-niveauet for JDK 1.8. For det meste kan du bare stole på, at den ved, hvad den laver. Som et eksempel kan du udelade versionsnummeret for mange almindelige afhængigheder, og SpringBootParent indstiller versionerne til at være kompatible. Når du støder op på forældrenes versionsnummer, ændres afhængighedsversionerne og standardindstillingerne også.
  2. Det spring-boot-maven-plugin muliggør den eksekverbare JAR / WAR-emballage og på plads løb (via mvn spring-boot: løb kommando).

Tilføjelse af Spring Web som en afhængighed

Indtil videre har vi været i stand til at bruge spring-boot for at begrænse, hvor meget arbejde vi lægger for at få en app i gang. Lad os nu tilføje en afhængighed og se, hvor hurtigt vi kan få noget i en browser.

Fortegnelse 7. Tilføjelse af Spring Web til et projekt

  org.springframework.boot spring-boot-starter-web 

Bemærk

Spring registrerer automatisk, hvilke filer der er ændret, og kompilerer i overensstemmelse hermed. Du kan bare udføre mvn spring-boot: løb til afhentningsændringer.

Nu hvor vi har en grundlæggende projektopsætning, er vi klar til vores to eksempler.

Eksempel nr. 2: Bygning af RESTfulde slutpunkter med Spring Web

Vi har brugt spring-boot-starter-web at bringe flere afhængigheder, der er nyttige til opbygning af webapplikationer. Dernæst opretter vi en rutehåndterer til en URL-sti. Spring's websupport er en del af Spring MVC (Model-View-Controller) -modulet, men lad det ikke bekymre dig: Spring Web har også fuld og effektiv support til at opbygge RESTful endpoints.

Den klasse, hvis opgave det er at stille URL-anmodninger, er kendt som en controller, som vist i liste 8.

Liste 8. Fjeder MVC REST controller

 pakke hej; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RequestParam; @Controller public class GreetingController {@RequestMapping (value = "/ hi", method = RequestMethod.GET) public String hi (@RequestParam (name = "name", required = false, defaultValue = "JavaWorld") String name, Model model ) {return "Hej" + navn; }} 

@Controller-kommentaren

Det @Kontrol annotation identificerer en klasse som en controller. En klasse markeret som en controller identificeres også automatisk som en komponentklasse, hvilket gør den til en kandidat til automatisk ledningsføring. Uanset hvor denne controller er nødvendig, vil den blive tilsluttet rammen. I dette tilfælde tilslutter vi det til MVC-systemet for at håndtere anmodninger.

Controlleren er en specialiseret komponent. Det understøtter @RequestMapping og @ResponseBody bemærkninger, som du ser på Hej() metode. Disse bemærkninger fortæller rammen om, hvordan man kortlægger URL-anmodninger til appen.

På dette tidspunkt kan du køre appen med mvn spring-boot: løb. Når du rammer /Hej URL, får du et svar som "Hej, JavaWorld."

Læg mærke til, hvordan Spring har taget det grundlæggende i autowiring-komponenter og leveret en hel webramme. Med Spring behøver du ikke eksplicit at forbinde noget sammen!

Kommentarerne til @Request

Det @RequestMapping giver dig mulighed for at definere en handler til en URL-sti. Valgmuligheder inkluderer at definere den ønskede HTTP-metode, hvilket er hvad vi har gjort i dette tilfælde. Forlader RequestMethod off vil instruere programmet om at håndtere alle HTTP-metodetyper.

Det @RequestParam argument-kommentar giver os mulighed for at kortlægge anmodningsparametrene direkte i metodesignaturen, herunder kræve visse parametre og definere standardværdier, som vi har gjort her. Vi kan endda kortlægge et anmodningsorgan til en klasse med @RequestBody argumentkommentar.

REST- og JSON-svar

Hvis du opretter et REST-slutpunkt, og du vil returnere JSON fra metoden, kan du kommentere metoden med @ResponseBody. Svaret pakkes derefter automatisk som JSON. I dette tilfælde returnerer du et objekt fra metoden.

Brug af MVC med Spring Web

I lighed med struts kan Spring Web-modulet let bruges til en ægte model-view-controller-opsætning. I så fald vil du returnere en kortlægning på det givne skabelonsprog (som Thymeleaf), og Spring ville løse kortlægningen, give den model, du sender til den, og gengive svaret.

Eksempel 3: Forår med JDBC

Lad os nu gøre noget mere interessant med vores anmodningshåndterer: lad os returnere nogle data fra en database. Med henblik på dette eksempel bruger vi H2-databasen. Heldigvis understøtter Spring Boot in-memory H2 DB ud af kassen.