@Scope singleton & prototype

Hallo, ich habe einen kleine Applikation geschriben um die @Scope Annotation zu testen. Leider finde ich den Fehler nicht.
Ich habe 4 Klassen: Main, Service, SingletonBean und PrototypeBean. Ich möchte die 2 Scope funktionen Testen. Meine Erwartung nach sollte die Console 0,1,0,0 ausgeben Da bei einem Singleton immer nur ein Bean erstellt wird und bei einem Prototype immer eine neue Instanz. Die Ausgabe in meiner Console schauen so aus: 1,0,1,0

Könnte mir einer erklären warum?

Main:

Java:
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TestApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }
}

Service:
Code:
package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Service {
    private final SingletonBean singletonBean;
    private final PrototypeBean prototypeBean;

    public Service(SingletonBean singletonBean, PrototypeBean prototypeBean) {
        this.singletonBean = singletonBean;
        this.prototypeBean = prototypeBean;
    }

    @Autowired
    public void testScopes() {
        System.out.println(singletonBean.getCounter()); // Ausgabe: 0
        System.out.println(singletonBean.getCounter()); // Ausgabe: 1

        System.out.println(prototypeBean.getCounter()); // Ausgabe: 0
        System.out.println(prototypeBean.getCounter()); // Ausgabe: 0
    }
}

SingletonBean:
Code:
package com.example.demo;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("singleton")
public class SingletonBean {
    private int counter = 0;

    public int getCounter() {
        return counter++;
    }
}

PrototypeBean:

Code:
package com.example.demo;

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("prototype")
public class PrototypeBean {
    private int counter = 0;

    public int getCounter() {
        return counter++;
    }
}
 

KonradN

Super-Moderator
Mitarbeiter
Ich verstehe gerade nicht, woher deine Erwartung kommt. Du hast doch nur einen Service. In diesem service wird einmalig jeweils ein Bean injected.

Dieser einmal im Konstruktor gesetzte Bean wird dann verwendet. Und dann wird in dem Bean bei jedem getCounter Aufruf counter um 1 erhöht.

Es wird also in dem Test eh immer genau ein Bean von jedem deiner Test Beans erstellt. Da nie ein zweiter Bean angefordert wird, kannst Du keinen Unterschied feststellen.

Da Du Spring verwendest: Du kannst einfach beim Spring Boot start (den run Aufruf) den ApplicationContext in einer Variablen speichern. Über den Context kannst Du die die Bean Instanzen holen. Das kannst Du mehrfach machen und statt dem getCounter() kannst Du einfach per System.out.println die Instanz ausgeben um zu sehen, ob Du immer die gleiche Instanz oder immer unterschiedliche Instanzen bekommst.
 
Ich habe mich an diese Aussage gehalten:

Eine Bean im Prototype-Scope wird jedes Mal, wenn darauf zugegriffen wird, neu erstellt. Jede Anfrage auf diese Bean erhält eine neue Instanz.

Da die Methode testScopes 2 mal auf prototypeBean zugreift, nehme ich an, dass beim 2 mal automatisch eine neue Instanz erstellt wird.
 

KonradN

Super-Moderator
Mitarbeiter
Ich habe mich an diese Aussage gehalten:

Eine Bean im Prototype-Scope wird jedes Mal, wenn darauf zugegriffen wird, neu erstellt. Jede Anfrage auf diese Bean erhält eine neue Instanz.

Da die Methode testScopes 2 mal auf prototypeBean zugreift, nehme ich an, dass beim 2 mal automatisch eine neue Instanz erstellt wird.
Die Formulierung ist so Quatsch. Wenn Du eine Referenz auf eine Instanz hast, dann verändert die sich ja nicht einfach so. Das wäre ja auch fatal wenn man sich das etwas überlegt, was das bedeuten würde.

Wenn man es umformulieren sollte, dann wäre es: "Immer, wenn der ApplicationContext auf den Bean zugreifen will, wird ein neuer Bean erstellt." Etwas in der Art.
 

Neue Themen


Oben