2011-04-01 88 views
7

我环顾四周寻找一种方法来提高JAXB解组表演处理文件的巨大集合,发现了以下建议:创建JAXB池的Unmarshaller

“如果你真正关心的性能,和/或你的应用程序将读取很多小文件,然后创建Unmarshaller可能是一个相对昂贵的操作。在这种情况下,考虑合并Unmarshaller对象“

谷歌搜索网络找到一个这样的例子没有返回任何东西,所以我认为使用Spring 3.0和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); 
    } 
} 

而在你的类,它需要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) { 
      } 
     } 
    } 

这个例子是天真的,因为它仅使用一个类来创建JAXBContext并使用与Keyed Po相同的Class实例醇。这可以通过传递一个类的数组作为参数而不是只有一个类来改进。

希望这可以帮助。

+3

严......这不是一个问题.... – lscoughlin 2011-04-01 07:53:44

+1

那么我不知道在哪里如何创建一个不是问题的话题。 – 2011-04-04 05:33:47

+0

嗨,我认为这很有价值,因此SO允许“回答自己的问题”,也许作为一个建议,你可以以问题的形式重构你的文章,并提供你的实现作为一个“答案”,然后你可以接受。 – 2012-09-11 07:15:39

回答

0

unmarshallers的创建旨在轻。我建议在制定合并策略之前进行一些分析。

+5

正如我所说,这一切都基于建议here告诉说,多个Unmarshallers的实例化可能是一个昂贵的操作。即使没有分析,我也可以告诉你,我们的应用运行速度更快,Unmarshaller池。 – 2011-04-04 05:37:14

+1

JXAB unmarshallers的创建不是轻而易举,无论其意图如何。 – Hector 2014-07-16 07:18:10