2013-02-23 13 views
14

Sono un neofita del framework primavera, iniziato con alcuni tutorial per impararlo.Spring bean destroy-method, singleton e prototype scope

ho seguenti file,

# MainProgram.java

package test.spring; 
import org.springframework.context.support.AbstractApplicationContext; 
import org.springframework.context.support.ClassPathXmlApplicationContext; 

public class MainProgram { 
     public static void main(String[] args) { 
       AbstractApplicationContext context = 
           new ClassPathXmlApplicationContext("Bean.xml");  
       HelloSpring obj = (HelloSpring) context.getBean("helloSpring"); 
       obj.setMessage("My message"); 
       obj.getMessage(); 
       context.registerShutdownHook(); 

     } 
} 

# HelloSpring.java

package test.spring; 

public class HelloSpring { 
    private String message; 

    public void setMessage(String message){ 
     this.message = message; 
     System.out.println("Inside setMessage"); 
    } 

    public void getMessage(){ 
     System.out.println("Your Message : " + this.message); 
    } 

    public void xmlInit() { 
    System.out.println("xml configured initialize"); 
    } 

    public void xmlDestroy() { 
    System.out.println("xml configured destroy"); 
    } 

    } 

# bean.xml

<?xml version="1.0" encoding="UTF-8"?> 
    <beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 

    <bean id="helloSpring" class="test.spring.HelloSpring" 
      scope="prototype" init-method="xmlInit" destroy-method="xmlDestroy"> 

    </bean> 
    </beans> 

Quando prendo scope="singleton" mio output è:

xml configured initialize 
Inside setMessage 
Your Message : My message 
xml configured destroy 

quando prendo scope="prototype" la mia uscita è:

xml configured initialize 
Inside setMessage 
Your Message : My message 

xmlDestroy() metodo viene chiamato con il fagiolo singleton portata ma non con prototype gentilmente aiutarmi per quanto segue,

Is questo è corretto? se sì, quali sarebbero le possibili ragioni?

Anche io ho alcune domande come,

ciò che è differenza o rapporto tra ApplicationContext , AbstractApplicationContext and ClassPathXmlApplicationContext

risposta

34

xmlDestroy() metodo è chiamato con il fagiolo portata singoletto ma non con prototipo perché

Spring non gestisce l'intero ciclo di vita di un fagiolo prototipo: le istanzia contenitore, configura, decora e altrimenti assembla un oggetto prototipo, porge a il cliente e quindi non ha più conoscenza di quell'istanza prototipo. Per il rilascio di risorse, provare ad implementare un post processore bean personalizzato.

A differenza di fagioli Singleton in cui il contenitore primavera gestisce il ciclo di vita completo

Si può avere uno sguardo a questo fondamentale tutorial per le differenze tra i diversi contesti

Riferirsi documentation

+0

Per il rilascio di risorse è possibile implementare DestructionAwareBeanPostProcessor anziché un ordinario BeanPostProcessor. –

1

Questo è il comportamento previsto. Spring non è in grado di sapere quando hai finito di utilizzare un bean di scope prototipo, quindi la distruzione dei bean non è gestita da Spring per i bean con scope prototipo. Dalla documentazione:

Sebbene i metodi di inizializzazione del ciclo di vita callback vengono chiamati tutti oggetti indipendentemente portata, nel caso di prototipi, configurato callback distruzione del ciclo di vita non sono chiamati.

Vedere Spring documentation per ulteriori informazioni.

Riguardo a ApplicationContext s, è possibile scegliere quello più adatto alla propria applicazione. Dipende se si desidera utilizzare la configurazione del bean di annotazione o XML e, ad esempio, se si sta eseguendo o meno in un contenitore di servlet. ApplicationContext è di per sé l'interfaccia nella radice del tipo heirarchy.

2

Un fagiolo Singleton significa che c'è esattamente un'istanza di quel bean nel contesto dell'applicazione. Ciò significa che se si fa qualcosa di simile:

HelloSpring obj = (HelloSpring) context.getBean("helloSpring"); 
    obj.setMessage("My message"); 
    System.out.printIn(obj.getMessage()); 
    HelloSpring anotherObj = (HelloSpring) context.getBean("helloSpring"); 
    System.out.printIn(anotherObj.getMessage()); 

Si vedrà "Il mio messaggio" in uscita della console per due volte.

Per i prototipi di fagioli ogni volta che si tenta di ottenere uno di quelli dal contesto dell'applicazione, si otterrà una nuova istanza, quindi se si esegue nuovamente il codice sopra, il secondo output della console sarà "null".

Poiché non è necessario che il contenitore chiami un metodo destroy per un bean prototipo, non lo fa e il comportamento è corretto.

La differenza tra le suddette classi è che sono rispettivamente un'interfaccia, una classe astratta e una classe concreta, per comprendere meglio tali concetti. Suggerisco di leggere la documentazione ufficiale di Oracle per Java qui Oracle Java Tutorials.

-1

Controllare il tipo di oscilloscopio nel file di configurazione di primavera. Se scope = "prototipo", quindi cambiare a scope = "Singleton"

<bean id="helloWorld" class="com.example.test.HelloWorld" 
init-method="init" destroy-method="destroy"> 
<property name="message" value="Hello World!" /> 

0

Ho anche cercato di ottenere un evento di distruzione di fagioli che è scopo è "prototipo". Quindi ho letto tutte le risposte sopra e provo con le loro risposte. Al risultato, raggiungo che non c'è modo di rilevare un distruggere anche il bean prototipo.

Sebbene i metodi di callback del ciclo di vita di inizializzazione siano richiamati su tutti gli oggetti indipendentemente dall'ambito, nel caso di prototipi, i callback del ciclo di vita della distruzione configurati non vengono chiamati.

vedi qui (https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-factory-scopes-prototype)

1

vostra applicazione potrebbe chiedere nuove istanze di fagioli prototipo ogni 10 millisecondi, fare qualcosa con il fagiolo, e poi lasciarlo andare fuori portata. Se Spring ha dovuto distruggerli() quando l'applicazione si arresta, dovrebbe mantenere un riferimento a ogni bean prototipo creato, impedendo che vengano raccolti da garbage collection e causando così una perdita di memoria.

Problemi correlati