2011-04-01 11 views
7

mi stava guardando attorno per trovare un modo per migliorare JAXB prestazioni unmarshalling l'elaborazione di enormi insiemi di file e ha trovato i seguenti consigli:creare un pool di JAXB unmarshaller

"Se davvero a cuore le prestazioni, e/o l'applicazione sta per leggere un sacco di piccoli documenti, quindi la creazione di unmarshaller potrebbe essere relativamente un'operazione costosa. In tal caso, prendere in considerazione mettendo in comune gli oggetti unmarshaller"

usare Google il web per trovare un esempio di questo non ha prodotto nulla , quindi ho pensato che potrebbe essere interessante mettere la mia implementazione qui usando Spring 3.0 e Apache Commons Pool.

UnmarshallerFactory.java

import java.util.HashMap; 
import java.util.Map; 
import javax.xml.bind.JAXBContext; 
import javax.xml.bind.JAXBException; 
import org.apache.commons.pool.KeyedPoolableObjectFactory; 
import org.springframework.stereotype.Component; 

/** 
* Pool of JAXB Unmarshallers. 
* 
*/ 
@Component 
public class UnmarshallerFactory implements KeyedPoolableObjectFactory { 
    // Map of JAXB Contexts 
    @SuppressWarnings("rawtypes") 
    private final static Map<Object, JAXBContext> JAXB_CONTEXT_MAP = new HashMap<Object, JAXBContext>(); 

    @Override 
    public void activateObject(final Object arg0, final Object arg1) throws Exception { 
    } 

    @Override 
    public void passivateObject(final Object arg0, final Object arg1) throws Exception { 
    } 

    @Override 
    public final void destroyObject(final Object key, final Object object) throws Exception { 
    } 

    /** 
    * Create a new instance of Unmarshaller if none exists for the specified 
    * key. 
    * 
    * @param unmarshallerKey 
    *   : Class used to create an instance of Unmarshaller 
    */ 
    @SuppressWarnings("rawtypes") 
    @Override 
    public final Object makeObject(final Object unmarshallerKey) { 
     if (unmarshallerKey instanceof Class) { 
      Class clazz = (Class) unmarshallerKey; 
      // Retrieve or create a JACBContext for this key 
      JAXBContext jc = JAXB_CONTEXT_MAP.get(unmarshallerKey); 
      if (jc == null) { 
       try { 
        jc = JAXBContext.newInstance(clazz); 
        // JAXB Context is threadsafe, it can be reused, so let's store it for later 
        JAXB_CONTEXT_MAP.put(unmarshallerKey, jc); 
       } catch (JAXBException e) { 
        // Deal with that error here 
        return null; 
       } 
      } 
      try { 
       return jc.createUnmarshaller(); 
      } catch (JAXBException e) { 
       // Deal with that error here 
      } 
     } 
     return null; 
    } 

    @Override 
    public final boolean validateObject(final Object key, final Object object) { 
     return true; 
    } 
} 

UnmarshallerPool.java

import org.apache.commons.pool.impl.GenericKeyedObjectPool; 
import org.apache.log4j.Logger; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Component; 

@Component 
public class UnmarshallerPool extends GenericKeyedObjectPool { 
    @Autowired 
    public UnmarshallerPool(final UnmarshallerFactory unmarshallerFactory) { 
    // Make usage of the factory created above 
    super(unmarshallerFactory); 
      // You'd better set the properties from a file here 
    this.setMaxIdle(4); 
    this.setMaxActive(5); 
    this.setMinEvictableIdleTimeMillis(30000); 
    this.setTestOnBorrow(false); 
    this.setMaxWait(1000); 
    } 

    public UnmarshallerPool(UnmarshallerFactory objFactory, 
     GenericKeyedObjectPool.Config config) { 
     super(objFactory, config); 
    } 

    @Override 
    public Object borrowObject(Object key) throws Exception { 
     return super.borrowObject(key); 
    } 

    @Override 
    public void returnObject(Object key, Object obj) throws Exception { 
     super.returnObject(key, obj); 
    } 
} 

E nella classe che richiedono un JAXB unmarshaller:

// Autowiring of the Pool 
    @Resource(name = "unmarshallerPool") 
    private UnmarshallerPool unmarshallerPool; 

    public void myMethod() { 
     Unmarshaller u = null; 
     try { 
      // Borrow an Unmarshaller from the pool 
      u = (Unmarshaller) this.unmarshallerPool.borrowObject(MyJAXBClass.class); 
      MyJAXBClass myJAXBObject = (MyJAXBClass) u.unmarshal(url); 
      // Do whatever 
     } catch (Exception e) { 
      // Deal with that error 
     } finally { 
      try { 
       // Return the Unmarshaller to the pool 
       this.unmarshallerPool.returnObject(MyJAXBClass.class, u); 
      } catch (Exception ignore) { 
      } 
     } 
    } 

Questo esempio è ingenuo in quanto utilizza una sola classe per creare la JAXBContext e utilizza la stessa istanza di classe della chiave per Keyed Po olo. Questo può essere migliorato passando una serie di classi come parametro piuttosto che una sola classe.

Spero che questo possa essere d'aiuto.

+3

Uhm .... questa non è una domanda .... – lscoughlin

+1

Beh, io non so dove posso creare un argomento che non è una domanda. –

+0

Hi hut, penso che questo sia prezioso e SO permette di "rispondere alle proprie domande", magari come un consiglio per ristrutturare il tuo post sotto forma di domanda e fornire la tua implementazione come una "risposta" che puoi accettare. –

risposta

0

La creazione di unmarshaller è concepita per essere leggera. Consiglierei di fare un po 'di profilazione prima di sviluppare una strategia di pooling.

+5

Come ho detto questo è tutto basato sul consiglio trovato here dicendo che l'istanziazione di Unmarshaller multipli può essere un'operazione costosa. Anche senza la creazione di profili, posso dirti che la mia app funziona molto più velocemente con il pool di Unmarshaller. –

+1

La creazione di unmarshallers JXAB NON è LUCE, qualunque sia l'intenzione. – Hector