Spring IoC und Spring Bean Beispiel

Spring Framework basiert auf dem Inversion of Control-Prinzip. Dependency Injection ist die Technik zur Implementierung von IoC in Anwendungen.

Spring IoC

Heute werden wir uns den Spring IoC Container ansehen. Wir werden auch Spring Bean durchgehen.

Spring IoC Container

Spring IoC ist der Mechanismus, um eine lose Kopplung zwischen Objektabhängigkeiten zu erreichen. Um eine lose Kopplung und dynamische Bindung der Objekte zur Laufzeit zu erreichen, werden Objektabhängigkeiten von anderen Montageobjekten injiziert. Der Spring IoC Container ist das Programm, das Abhängigkeiten in ein Objekt injiziert und es für unseren Gebrauch vorbereitet. Wir haben bereits betrachtet, wie wir Spring Dependency Injection verwenden können, um IoC in unseren Anwendungen zu implementieren. Klassen des Spring IoC Containers sind Teil der Pakete org.springframework.beans und org.springframework.context. Der Spring IoC Container bietet uns verschiedene Möglichkeiten, die Objektabhängigkeiten zu entkoppeln. BeanFactory ist das Wurzelinterface des Spring IoC Containers. ApplicationContext ist das untergeordnete Interface des BeanFactory-Interfaces, das Spring AOP-Funktionen, i18n usw. bietet. Einige der nützlichen untergeordneten Interfaces von ApplicationContext sind ConfigurableApplicationContext und WebApplicationContext. Spring Framework bietet eine Reihe nützlicher ApplicationContext-Implementierungsklassen, die wir verwenden können, um den Spring-Kontext und dann den Spring Bean zu erhalten. Einige der nützlichen ApplicationContext-Implementierungen, die wir verwenden, sind:

  • AnnotationConfigApplicationContext: Wenn wir Spring in eigenständigen Java-Anwendungen verwenden und Annotationen für die Konfiguration verwenden, dann können wir dies verwenden, um den Container zu initialisieren und die Bean-Objekte zu erhalten.
  • ClassPathXmlApplicationContext: Wenn wir eine XML-Konfigurationsdatei für Spring Bean in einer eigenständigen Anwendung haben, dann können wir diese Klasse verwenden, um die Datei zu laden und das Containerobjekt zu erhalten.
  • FileSystemXmlApplicationContext: Dies ist ähnlich wie ClassPathXmlApplicationContext, außer dass die XML-Konfigurationsdatei von überall im Dateisystem geladen werden kann.
  • AnnotationConfigWebApplicationContext und XmlWebApplicationContext für Webanwendungen.

Normalerweise, wenn Sie an einer Spring MVC-Anwendung arbeiten und Ihre Anwendung so konfiguriert ist, dass sie Spring Framework verwendet, wird der Spring IoC Container initialisiert, wenn die Anwendung startet, und wenn ein Bean angefordert wird, werden die Abhängigkeiten automatisch injiziert. Für eine eigenständige Anwendung müssen Sie jedoch irgendwo in der Anwendung den Container initialisieren und ihn dann verwenden, um die Spring Beans zu erhalten.

Spring Bean

Spring Bean ist nichts Besonderes, jedes Objekt im Spring Framework, das wir über den Spring Container initialisieren, wird als Spring Bean bezeichnet. Jede normale Java POJO-Klasse kann ein Spring Bean sein, wenn sie so konfiguriert ist, dass sie über den Container durch Bereitstellung von Konfigurations-Metadateninformationen initialisiert wird.

Spring Bean Scopes

Es gibt fünf definierte Bereiche für Spring Beans.

  • singleton – Für jeden Container wird nur eine Instanz des Beans erstellt. Dies ist der Standardbereich für die Spring Beans. Achten Sie bei der Verwendung dieses Bereichs darauf, dass der Bean keine gemeinsam genutzten Instanzvariablen hat, da dies zu Dateninkonsistenzproblemen führen kann.
  • prototype – Bei jeder Anforderung des Beans wird eine neue Instanz erstellt.
  • request – Dies ist dasselbe wie der prototype-Bereich, jedoch ist es für Webanwendungen gedacht. Für jede HTTP-Anforderung wird eine neue Instanz des Beans erstellt.
  • session – Für jede HTTP-Sitzung wird vom Container ein neuer Bean erstellt.
  • global-session – Dies wird verwendet, um globale Session-Beans für Portlet-Anwendungen zu erstellen.

Spring Framework ist erweiterbar, und wir können auch unsere eigenen Bereiche erstellen. Allerdings sind wir meistens mit den vom Framework bereitgestellten Bereichen gut bedient.

Spring Bean Konfiguration

Spring Framework bietet drei Möglichkeiten, Beans für die Verwendung in der Anwendung zu konfigurieren.

  • Annotation Based Configuration – Durch die Verwendung von @Service oder @Component Annotationen. Bereichsdetails können mit der @Scope Annotation angegeben werden.
  • XML Based Configuration – Durch das Erstellen einer Spring-Konfigurations-XML-Datei zur Konfiguration der Beans. Wenn Sie das Spring MVC Framework verwenden, kann die XML-basierte Konfiguration automatisch geladen werden, indem Sie etwas Boilerplate-Code in der web.xml-Datei schreiben.
  • Java Based Configuration – Ab Spring 3.0 können wir Spring Beans mit Java-Programmen konfigurieren. Einige wichtige Annotationen, die für die Java-basierte Konfiguration verwendet werden, sind @Configuration, @ComponentScan und @Bean.

Spring IoC und Spring Bean Beispielprojekt

Lassen Sie uns die verschiedenen Aspekte des Spring IoC Containers und der Spring Bean-Konfigurationen mit einem einfachen Spring-Projekt betrachten. Für mein Beispiel erstelle ich ein Spring MVC-Projekt in Spring Tool Suite. Wenn Sie neu in Spring Tool Suite und Spring MVC sind, lesen Sie bitte das Spring MVC Tutorial mit Spring Tool Suite. Die endgültige Projektstruktur sieht wie das untenstehende Bild aus.

Spring IoC Container, Spring Bean Beispiel

Lassen Sie uns die verschiedenen Komponenten des Spring IoC und Spring Bean Projekts einzeln betrachten.

XML-basierte Spring Bean-Konfiguration

MyBean – Eine einfache 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 File

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:beans>

Beachten Sie, dass MyBean mit dem Bean-Element konfiguriert ist, wobei der Scope als singleton festgelegt ist.

Annotation Based Spring Bean Konfiguration

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 ist mit @Service konfiguriert und der Scope ist auf Request gesetzt.

Spring IoC Controller Klasse

Die HomeController-Klasse wird die HTTP-Anfragen für die Startseite der Anwendung behandeln. Wir werden unsere Spring Beans über den WebApplicationContext-Container in diese Controller-Klasse injizieren.

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";
    }
    
}

Deployment Descriptor

Wir müssen unsere Anwendung für das Spring Framework konfigurieren, damit die Konfigurations-Metadaten geladen und der Kontext initialisiert werden.

<?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>

Fast die gesamte oben genannte Konfiguration ist Boilerplate-Code, der automatisch vom STS-Tool generiert wird.

Starten Sie die Spring IoC Bean Beispielanwendung

Wenn Sie jetzt die Webanwendung starten, wird die Startseite geladen und in der Konsole werden die folgenden Logs gedruckt, wenn Sie die Seite mehrmals aktualisieren.

MyBean hashcode=118267258
MyAnnotatedBean hashcode=1703899856
MyBean hashcode=118267258
MyAnnotatedBean hashcode=1115599742
MyBean hashcode=118267258
MyAnnotatedBean hashcode=516457106

Beachten Sie, dass MyBean so konfiguriert ist, dass es ein Singleton ist, sodass der Container immer dieselbe Instanz zurückgibt und der Hashcode immer gleich ist. Ebenso wird für jede Anfrage eine neue Instanz von MyAnnotatedBean mit unterschiedlichem Hashcode erstellt.

Java Based Spring Bean Konfiguration

Für eigenständige Anwendungen können wir sowohl annotation based als auch XML based Konfiguration verwenden. Die einzige Voraussetzung ist, den Kontext irgendwo im Programm zu initialisieren, bevor wir ihn verwenden.

MyService – Eine einfache Java-Klasse

package com.journaldev.spring.main;

public class MyService {
    public void log(String msg){
        System.out.println(new Date()+"::"+msg);
    }
}

MyService ist eine einfache Java-Klasse mit einigen 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();
    }
}

Die auf Annotationen basierende Konfigurationsklasse, die verwendet wird, um den Spring-Container zu initialisieren.

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();
    }
}

Ein einfaches Testprogramm, bei dem wir den AnnotationConfigApplicationContext-Kontext initialisieren und dann die Methode getBean() verwenden, um die Instanz von MyService zu erhalten. Beachten Sie, dass ich die Methode getBean zweimal aufrufe und den Hashcode ausdrucke. Da für MyService kein Scope definiert ist, sollte es ein Singleton sein, und daher sollte der Hashcode für beide Instanzen gleich sein.

Wenn wir die obige Anwendung ausführen, erhalten wir die folgende Konsolenausgabe, die unser Verständnis bestätigt.

Sat Dec 28 22:49:18 PST 2013::Hi
service hashcode=678984726
newService hashcode=678984726

XML-basierte Konfiguration

Wenn Sie eine XML-basierte Konfiguration suchen, erstellen Sie einfach die Spring XML-Konfigurationsdatei und initialisieren Sie dann den Kontext mit dem folgenden Code-Snippet.

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                "applicationContext.xml");
        MyService app = context.getBean(MyService.class);

Das ist alles für das Spring IoC-Beispieltutorial, die Spring Bean Scopes und die Konfigurationsdetails.

Kostenlosen Account erstellen

Registrieren Sie sich jetzt und erhalten Sie Zugang zu unseren Cloud Produkten.

Das könnte Sie auch interessieren: