2011-04-01 2 views
7

내가 파일의 큰 세트를 처리하는 JAXB 비 정렬 화의 성능을 향상시킬 수있는 방법을 찾아 둘러보고 된 JAXB의 풀을 Unmarshaller에를 만들고 발견다음과 같은 조언을

"당신이 정말로, 성능에 대해 걱정하는 경우 및/또는 응용 프로그램이 많은 작은 문서를 읽는다면 Unmarshaller를 만드는 것이 상대적으로 비용이 많이 드는 작업 일 수 있습니다.이 경우 Unmarshaller 객체를 풀링하는 것이 좋습니다. "

예를 찾기 위해 웹 검색을하면 아무것도 반환되지 않았습니다. 그래서 Spring 3.0과 Apache Commons Pool을 사용하여 여기에 구현하는 것이 흥미로울 것이라고 생각했다. JAXB 프로 Unmarshaller에이 필요

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); 
    } 
} 

그리고 당신의 클래스

UnmarshallerFactory.java

: 그것은을 만드는 데 하나 개의 클래스를 사용하기 때문에

// 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 인스턴스를 사용합니다. ol. 이것은 하나의 클래스가 아니라 매개 변수로 클래스 배열을 전달함으로써 향상시킬 수 있습니다.

희망이 도움이 될 수 있습니다.

+3

음 ....이 질문은 .... 아니. – lscoughlin

+1

글쎄, 내가 어디서 어떻게 질문을하지 않는 주제를 만들 수 있는지 모르겠다. –

+0

안녕하세요, 저는 이것이 가치가 있다고 생각합니다. 그래서 SO는 "자신의 질문에 대답"을 할 수 있습니다. 아마도 당신이 질문의 형태로 게시물을 재구성 할 수 있고 당신이 받아 들일 수있는 "대답"으로 당신의 구현을 제공 할 수 있습니다. –

답변

0

언 마샬 러의 작성은 가볍습니다. 풀링 전략을 개발하기 전에 프로파일 링을하는 것이 좋습니다.

+5

내가 말했듯이 이것은 복수의 Unmarshallers의 인스턴스 생성이 값 비싼 작업이 될 수 있다고 말하는 조언에 기반하고 있습니다 (here). 프로파일 링이 없어도 Unmarshaller 풀링을 사용하면 내 앱이 훨씬 빠르게 실행됩니다. –

+1

JXAB unmarshallers의 작성은 의도가 무엇이든간에 가볍지 않습니다. – Hector