Welkom bij de Spring IoC Voorbeeld Tutorial. Het Spring Framework is gebaseerd op het principe van Inversie van Controle. Dependency injection is de techniek om IoC in applicaties te implementeren.
Spring IoC
Vandaag zullen we de Spring IoC Container bekijken. We zullen ook door Spring Bean gaan. Hieronder staat de inhoudsopgave voor snelle navigatie naar verschillende secties van de Spring IoC tutorial.
- Spring IoC
- Spring Bean
- Spring Bean Scopes
- Spring Bean Configuration
- Spring IoC en Spring Bean Voorbeeld
Spring IoC Container
Spring IoC is het mechanisme om een losse koppeling tussen objectafhankelijkheden te bereiken. Om een losse koppeling en dynamische binding van de objecten tijdens runtime te realiseren, worden objectafhankelijkheden geïnjecteerd door andere assemblerende objecten. De Spring IoC-container is het programma dat afhankelijkheden injecteert in een object en het gereed maakt voor ons gebruik. We hebben al bekeken hoe we Spring Dependency Injection kunnen gebruiken om IoC in onze toepassingen te implementeren. De klassen van de Spring IoC-container maken deel uit van de pakketten org.springframework.beans
en org.springframework.context
. De Spring IoC-container biedt ons verschillende manieren om de afhankelijkheden van objecten te ontkoppelen. BeanFactory
is de hoofdinterface van de Spring IoC-container. ApplicationContext
is de onderliggende interface van de BeanFactory
-interface die Spring AOP-functies, i18n, enzovoort biedt. Enkele nuttige onderliggende interfaces van ApplicationContext
zijn ConfigurableApplicationContext
en WebApplicationContext
. Het Spring Framework biedt verschillende handige implementatieklassen van ApplicationContext die we kunnen gebruiken om de Spring-context en vervolgens de Spring Bean te verkrijgen. Enkele nuttige implementaties van ApplicationContext die we gebruiken zijn;
- AnnotationConfigApplicationContext: Als we Spring gebruiken in op zichzelf staande Java-toepassingen en annotaties gebruiken voor configuratie, dan kunnen we deze gebruiken om de container te initialiseren en de bean-objecten te verkrijgen.
- ClassPathXmlApplicationContext: Als we een spring bean configuratie xml-bestand hebben in een op zichzelf staande applicatie, dan kunnen we deze klasse gebruiken om het bestand te laden en het containerobject te krijgen.
- FileSystemXmlApplicationContext: Dit is vergelijkbaar met ClassPathXmlApplicationContext, behalve dat het xml-configuratiebestand vanaf elke locatie in het bestandssysteem kan worden geladen.
- AnnotationConfigWebApplicationContext en XmlWebApplicationContext voor webapplicaties.
Gewoonlijk, als je aan een Spring MVC-applicatie werkt en je applicatie is geconfigureerd om Spring Framework te gebruiken, wordt de Spring IoC-container geïnitialiseerd wanneer de applicatie start en worden wanneer een bean wordt aangevraagd, de afhankelijkheden automatisch ingespoten. Voor een op zichzelf staande applicatie moet je echter ergens in de applicatie de container initialiseren en deze vervolgens gebruiken om de spring beans te verkrijgen.
Spring Bean
Een Spring Bean is niets bijzonders, elk object in het Spring-framework dat we initialiseren via de Spring-container wordt een Spring Bean genoemd. Elke normale Java POJO-klasse kan een Spring Bean zijn als deze geconfigureerd is om via de container te worden geïnitialiseerd door configuratiemetadata-informatie te verstrekken.
Spring Bean Scopes
Er zijn vijf scopes gedefinieerd voor Spring Beans.
- singleton – Er wordt slechts één instantie van de bean aangemaakt voor elke container. Dit is de standaardscope voor de Spring Beans. Bij gebruik van deze scope, zorg ervoor dat de bean geen gedeelde instantievariabelen heeft, anders kan dit leiden tot inconsistentie in de gegevens.
- prototype – Er wordt elke keer een nieuwe instantie aangemaakt wanneer de bean wordt aangevraagd.
- request – Dit is hetzelfde als de prototype-scope, maar is bedoeld voor gebruik in webapplicaties. Er wordt een nieuwe instantie van de bean aangemaakt voor elke HTTP-request.
- session – Voor elke HTTP-sessie wordt door de container een nieuwe bean aangemaakt.
- global-session – Dit wordt gebruikt om wereldwijde sessiebeans te maken voor Portlet-applicaties.
Het Spring Framework is uitbreidbaar en we kunnen ook onze eigen scopes maken. Maar meestal voldoen de scopes die door het framework worden aangeboden.
Spring Bean-configuratie
Het Spring Framework biedt drie manieren om beans te configureren die in de applicatie moeten worden gebruikt.
- Configuratie op basis van annotaties – Door gebruik te maken van annotaties zoals @Service of @Component. Details over de scope kunnen worden toegevoegd met de @Scope annotatie.
- Configuratie op basis van XML – Door een Spring Configuration XML-bestand te maken om de beans te configureren. Als je het Spring MVC-framework gebruikt, kan de op XML gebaseerde configuratie automatisch worden geladen door wat basiscode in het web.xml-bestand te schrijven.
- Configuratie op basis van Java – Vanaf Spring 3.0 kunnen we Spring beans configureren met behulp van Java-programma’s. Enkele belangrijke annotaties die worden gebruikt voor op Java gebaseerde configuratie zijn @Configuration, @ComponentScan en @Bean.
Voorbeeldproject van Spring IoC en Spring Bean
Laten we eens kijken naar de verschillende aspecten van de Spring IoC-container en Spring Bean-configuraties met een eenvoudig Spring-project. Voor mijn voorbeeld maak ik een Spring MVC-project in Spring Tool Suite. Als je nieuw bent in Spring Tool Suite en Spring MVC, lees dan Spring MVC Tutorial met Spring Tool Suite. De uiteindelijke projectstructuur ziet eruit als de onderstaande afbeelding. Laten we eens kijken naar de verschillende componenten van Spring IoC en Spring Bean-project één voor één.
XML-gebaseerde Spring Bean-configuratie
MyBean is een eenvoudige Java POJO-klasse.
package com.journaldev.spring.beans;
public class MyBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Spring Configuration XML-bestand
servlet-context.xml code:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="https://www.springframework.org/schema/mvc"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="https://www.springframework.org/schema/beans"
xmlns:context="https://www.springframework.org/schema/context"
xsi:schemaLocation="https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.journaldev.spring" />
<beans:bean name="myBean" class="com.journaldev.spring.beans.MyBean" scope="singleton" ></beans:bean>
</beans:beans>
Merk op dat MyBean geconfigureerd is met behulp van het bean
-element met scope als singleton.
Op annotaties gebaseerde Spring Bean-configuratie
package com.journaldev.spring.beans;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.web.context.WebApplicationContext;
@Service
@Scope(WebApplicationContext.SCOPE_REQUEST)
public class MyAnnotatedBean {
private int empId;
public int getEmpId() {
return empId;
}
public void setEmpId(int empId) {
this.empId = empId;
}
}
MyAnnotatedBean is geconfigureerd met @Service en de scope is ingesteld op Aanvraag.
Spring IoC Controller Class
De HomeController-klasse zal de HTTP-verzoeken voor de startpagina van de applicatie afhandelen. We zullen onze Spring-beans injecteren in deze controllerklasse via de WebApplicationContext-container.
package com.journaldev.spring.controller;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
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 com.journaldev.spring.beans.MyAnnotatedBean;
import com.journaldev.spring.beans.MyBean;
@Controller
@Scope("request")
public class HomeController {
private MyBean myBean;
private MyAnnotatedBean myAnnotatedBean;
@Autowired
public void setMyBean(MyBean myBean) {
this.myBean = myBean;
}
@Autowired
public void setMyAnnotatedBean(MyAnnotatedBean obj) {
this.myAnnotatedBean = obj;
}
/**
* Simply selects the home view to render by returning its name.
*/
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
System.out.println("MyBean hashcode="+myBean.hashCode());
System.out.println("MyAnnotatedBean hashcode="+myAnnotatedBean.hashCode());
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
return "home";
}
}
Implementatiebeschrijving
We moeten onze toepassing configureren voor het Spring Framework, zodat de configuratiemetadata wordt geladen en de context wordt geïnitialiseerd.
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="https://java.sun.com/xml/ns/javaee"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Bijna alle bovenstaande configuratie is boilerplate-code die automatisch wordt gegenereerd door de STS-tool.
Voer de voorbeeldtoepassing van de Spring IoC-bean uit
Wanneer je nu de webtoepassing start, wordt de startpagina geladen en worden bij het vernieuwen van de pagina meerdere keren de volgende logboeken afgedrukt in de console.
MyBean hashcode=118267258
MyAnnotatedBean hashcode=1703899856
MyBean hashcode=118267258
MyAnnotatedBean hashcode=1115599742
MyBean hashcode=118267258
MyAnnotatedBean hashcode=516457106
Merk op dat MyBean geconfigureerd is om een singleton te zijn, dus de container retourneert altijd dezelfde instantie en de hashcode is altijd hetzelfde. Op dezelfde manier wordt voor elke aanvraag een nieuwe instantie van MyAnnotatedBean gemaakt met een andere hashcode.
Configuratie van op Java gebaseerde Spring Bean
Voor op zichzelf staande toepassingen kunnen we zowel op annotaties gebaseerde als op XML-gebaseerde configuratie gebruiken. De enige vereiste is om de context ergens in het programma te initialiseren voordat we deze gebruiken.
package com.journaldev.spring.main;
import java.util.Date;
public class MyService {
public void log(String msg){
System.out.println(new Date()+"::"+msg);
}
}
MyService is een eenvoudige Java-klasse met enkele methoden.
package com.journaldev.spring.main;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(value="com.journaldev.spring.main")
public class MyConfiguration {
@Bean
public MyService getService(){
return new MyService();
}
}
De op annotaties gebaseerde configuratieklasse die zal worden gebruikt om de Spring-container te initialiseren.
package com.journaldev.spring.main;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MyMainClass {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
MyConfiguration.class);
MyService service = ctx.getBean(MyService.class);
service.log("Hi");
MyService newService = ctx.getBean(MyService.class);
System.out.println("service hashcode="+service.hashCode());
System.out.println("newService hashcode="+newService.hashCode());
ctx.close();
}
}
A simple test program where we are initializing the AnnotationConfigApplicationContext
context and then using getBean()
method to get the instance of MyService. Notice that I am calling getBean method two times and printing the hashcode. Since there is no scope defined for MyService, it should be a singleton and hence hashcode should be the same for both the instances. When we run the above application, we get following console output confirming our understanding.
Sat Dec 28 22:49:18 PST 2013::Hi
service hashcode=678984726
newService hashcode=678984726
Als u op zoek bent naar XML-gebaseerde configuratie, maak dan gewoon het Spring XML-configuratiebestand en initialiseer vervolgens de context met de volgende code.
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml");
MyService app = context.getBean(MyService.class);
Dat is alles voor het Spring IoC-voorbeeldzelfstudie, Spring Bean Scopes en Configuratiedetails. Download het Spring IoC- en Spring Bean-voorbeeldproject van onderstaande link en experimenteer ermee voor een beter begrip.
Spring Beans Project Downloaden
Referentie: Spring.IO Pagina voor IOC
Source:
https://www.digitalocean.com/community/tutorials/spring-ioc-bean-example-tutorial