2011-04-01 12 views
7

que estaba buscando alrededor para encontrar una manera de mejorar el rendimiento unmarshalling JAXB el procesamiento de grandes conjuntos de archivos y encontró el siguiente consejo:crear un grupo de JAXB Unmarshaller

"Si realmente se preocupan por el rendimiento, y/o su aplicación va a leer muchos documentos pequeños, entonces la creación de Unmarshaller podría ser una operación relativamente costosa. En ese caso, considere agrupar objetos Unmarshaller "

Google buscando en la web para encontrar un ejemplo de esto no devolvió nada , así que pensé que sería interesante poner mi implementación aquí usando Spring 3.0 y 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); 
    } 
} 

Y en su clase que requiere una 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) { 
      } 
     } 
    } 

Este ejemplo es ingenua, ya que utiliza una sola clase para crear la JAXBContext y utiliza la misma instancia de clase que la clave para el Po con clave ol. Esto puede mejorarse pasando un conjunto de clases como parámetro en lugar de solo una clase.

Espero que esto te pueda ayudar.

+3

Uhm .... esto no es una pregunta .... – lscoughlin

+1

Bueno, no sé dónde, cómo puedo crear un tema que no sea una pregunta. –

+0

Hola, pero creo que esto es valioso y, por lo tanto, permite "responder preguntas propias", tal vez como consejo podrías reestructurar tu publicación en forma de pregunta y proporcionar tu implementación como una "respuesta" que luego puedes aceptar. –

Respuesta

0

La creación de unmarshallers está destinada a ser liviana. Recomendaría hacer algunos perfiles antes de desarrollar una estrategia de agrupamiento.

+5

Como dije, todo esto se basa en el consejo encontrado here diciendo que la creación de instancias de Unmarshallers múltiples puede ser una operación costosa. Incluso sin crear perfiles, puedo decirte que mi aplicación se ejecuta mucho más rápido con Unmarshaller. –

+1

La creación de unmarshallers JXAB NO ES LIGERA, sea cual sea la intención. – Hector

Cuestiones relacionadas