2017-09-26 11 views
1

Je travaille sur Java depuis plus de 4 ans mais je suis nouveau sur Spring. Je suis confronté à problème pour l'initialisation vide List pour chaque demande PUT.Effacer/Initialiser la liste (Collection) pour chaque requête HTTP au printemps

enter image description here

  • public abstract class BaseX implements InterfaceX
  • public class DefaultX extends BaseX
  • public class DefaultXAndY extends DefaultX

Issue:

List utilisé dans La classe BaseX n'efface pas pour chaque requête HTTP PUT. Le code est comme suit.

InterfaceX.java

public interface InterfaceX { 
    public void process(Long id); 
    public void publish(); 
} 

BaseX.java

import java.util.ArrayList; 
import java.util.List; 

import org.springframework.stereotype.Component; 

@Component 
public abstract class BaseX implements InterfaceX{ 
    private List<Long> listLong = new ArrayList<Long>(); 

    public void addToList(Long id){ 
     System.out.println("Here in BaseX"); 
     listLong.add(id); 
    } 

    @Override 
    public void publish() { 
     System.out.println("Print list values"); 
     listLong.stream().forEach(System.out::println); 
    } 
} 

DefaultX.java

import javax.annotation.Resource; 

import org.springframework.stereotype.Component; 

@Component 
@Resource(name = "defaultX") 
public class DefaultX extends BaseX{ 

    @Override 
    public void process(Long id) { 
     //business logic 
     System.out.println("Here in DefaultX"); 
     addToList(id); 
    } 
} 

DefaultXAndY.java

import javax.annotation.Resource; 
import org.springframework.stereotype.Component; 

@Component 
@Resource(name = "defaultXAndY") 
public class DefaultXAndY extends DefaultX{ 
    @Override 
    public void process(Long id) { 
     //Business logic different than X 
     System.out.println("Here in DefaultXAndY"); 
     id = id + 10; 
     super.process(id); 
    } 
} 

TestService.java

public interface TestService { 
    public void testServiceMethod(Long id); 
} 

TestServiceImpl

import javax.annotation.Resource; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Service; 
import com.orderhive.inventory.service.TestService; 
import com.orderhive.inventory.stock.InterfaceX; 

@Service 
public class TestServiceImpl implements TestService{ 

    @Autowired 
    @Resource(name = "defaultXAndY") 
    private InterfaceX interfaceX; 

    @Override 
    public void testServiceMethod(Long id) { 
     interfaceX.process(id); 
     interfaceX.publish(); 
     System.out.println("API call finished for id: " + id); 
     System.out.println("--------------------------------"); 
    } 
} 

TestRestController
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.web.bind.annotation.PathVariable; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.bind.annotation.RestController; 

import com.orderhive.inventory.service.TestService; 

@RestController 
@RequestMapping("/test") 
public class TestRestController { 

    @Autowired 
    private TestService testService; 

    @RequestMapping(method = RequestMethod.PUT, value = "/number/{id}") 
    void stockUpdate(@PathVariable Long id){ 
     testService.testServiceMethod(id); 
    } 
} 

sortie

**PUT: localhost:8080/test/number/1** 

Here in DefaultXAndY 
Here in DefaultX 
Here in BaseX 
Print list values 
11 
API call finished for id: 1 
-------------------------------- 
**PUT: localhost:8080/test/number/2** 

Here in DefaultXAndY 
Here in DefaultX 
Here in BaseX 
Print list values 
11 
12 
API call finished for id: 2 
-------------------------------- 

List est de maintien de valeur de requête précédente.

============================================== =============

MISE à JOUR

les modifications suivantes ont travaillé pour moi, mais est-ce la meilleure pratique?

  • enlevé @Component de BaseX
  • @Scope("request") ajouté dans DefaultX et DefaultXAndY
  • @Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS) ajouté à TestServiceImpl suggéré par @ Anatoly-shamov

============ =====================================================

Solution:

  • retiré @Component de BaseX
  • @Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS) ajouté en DefaultX et DefaultXAndY
+0

ont u jamais utilisé la notation @Bean. Utilisez @Bean avec la portée 'request' ou 'prototype'. parce que les étendues par défaut du haricot est Singlton. –

+0

Puisque 'Basex' est un composant Spring (Bean), les variables globales contiendront les valeurs précédentes. Il ne détruira pas de conteneur de printemps car il est singleton –

+0

jeter un oeil à >> https://stackoverflow.com/questions/7621920/scopeprototype-bean-scope-not-creating-new-bean –

Répondre

1

BaseX est un haricot de singleton scope (par défaut). Cela signifie qu'il n'y a qu'une instance de BaseX dans le conteneur IoC de Spring. Toutes les demandes et références pour ce bean renvoie le même objet. Vous devez extraire l'état listLong avec un bean séparé de request scope. Une nouvelle instance de ce bean sera créée pour chaque requête HTTP.

@Component 
@Scope(value = "request", proxyMode= ScopedProxyMode.TARGET_CLASS) 
public class ListX { 
    private List<Long> listLong = new ArrayList<Long>(); 

    public List<Long> getListLong() { 
     return listLong; 
    } 

    public void setListLong(List<Long> listLong) { 
     this.listLong = listLong; 
    } 
} 

Utilisez en tant que titulaire listLong de valeur dans d'autres composants:

@Component 
public abstract class BaseX implements InterfaceX{ 

    @Autowired 
    ListX listHolder; 

    public void addToList(Long id){ 
     System.out.println("Here in BaseX"); 
     listHolder.getListLong().add(id); 
    } 

    @Override 
    public void publish() { 
     System.out.println("Print list values"); 
     listHolder.getListLong().stream().forEach(System.out::println); 
    } 
} 
+0

Je vais sûrement essayer cela mais compte tenu de votre réponse, je dois faire de même pour les autres variables dans la classe 'DefaultX' et' DefaultXAndY'. Pouvons-nous obtenir une nouvelle instance de 'DefaultXAndY' pour chaque requête? –

+0

Bien sûr, vous pouvez. Mettez simplement une annotation @Scope (value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS) sur la classe DefaultXAndY. –

+0

Pouvez-vous s'il vous plaît vérifier le ** MISE À JOUR ** –