2012-06-13 47 views
3

我正在使用JAXB 2.0版本。对于此,我以下列方式创建JAXBContext对象:在静态块中放置昂贵的资源创建?

package com; 

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.JAXBException; 

public class JAXBContextFactory { 

    public static JAXBContext createJAXBContext() throws JAXBException { 
     JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class); 

     return jaxbContext; 
    } 

} 

基本上因为创建的JAXBContext是非常昂贵的,我想创建JAXBContext一次且仅一次为整个应用程序。所以我把JAXBContext的代码放在静态方法中,如上所示。

现在,只要需要参考JAXBContex,请求就会调用JAXBContextFactory.createJAXBContext();现在我的问题是,在这种情况下JAXBContext只创建一次,或者应用程序会有多个JAXBContext的实例吗?

+1

看看Singleton设计模式。 http://en.wikipedia.org/wiki/Singleton_pattern – climbage

+0

Dup:http://stackoverflow.com/questions/794354/jaxbcontext-initialization-speedup – wrschneider

+0

@Vipar不是真的,我实际上没有回答他的问题 – climbage

回答

5

每次调用此方法时,您的应用程序都会有一个JAXBContext实例。

如果你不希望这样的事情发生,你需要做以下的事情

package com; 

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.JAXBException; 

public class JAXBContextFactory { 

    private static JAXBContext context = null; 
    public static synchronized JAXBContext createJAXBContext() throws JAXBException { 
     if(context == null){ 
      context = JAXBContext.newInstance(Customer.class); 
     } 
     return context; 
    } 

} 

这之间的差异以及实现的是,在这其中,我们保存在创建的JAXBContext实例一个静态变量(保证只存在一次)。在你的实现中,你不是在任何地方保存刚创建的实例,而是每次调用该方法时创建一个新实例。重要提示:不要忘记添加到方法声明中的​​关键字,因为它确保在多线程环境中调用此方法仍将按预期工作。

+0

非常感谢您的解释。我现在非常清楚这个概念。再次感谢 。 – Pawan

+0

我还有一个问题,我看到我可以使用静态块实现JAXBContext的单个实例,或者如果(context == null)以这种方式执行检查的帮助,任何人都可以告诉我,有什么区别和什么是可取的?? – Pawan

+2

如果将它放入静态初始化块中,则在JVM首次启动类时(基本上,当JVM首先发现JAXBContextFactory类存在时),将会创建实例,该实例可能是随时随地且不受您控制的。这基本上是主动初始化。如果您在createJAXBContext()方法中执行此操作,则只会在第一次调用该方法时创建实例。这是懒惰的初始化。 – LordOfThePigs

3

您的实现将为每个请求创建一个新的JAXBContext。相反,你可以这样做:

public class JAXBContextFactory { 
    private static JAXBContext jaxbContext; 

    static { 
     try { 
      jaxbContext = JAXBContext.newInstance(Customer.class); 
     } catch (JAXBException ignored) { 
     } 
    } 

    public static JAXBContext createJAXBContext() { 
     return jaxbContext; 
    } 

} 
+3

您可能想要抛出一个AssertionError,而不是忽略异常。 –

+1

并使静态最终。 –

+0

这真的没什么关系,但我同意:)顺便说一句,我认为这比在方法上同步更好,就像下面的答案一样。如果应用程序实际上正在使用此功能,则可能还会在类加载时初始化静态值,并跳过每个方法调用的同步。 –

1

每次调用方法时都会有一个实例。使用static方面只是意味着你不具备JAXBContextFactory

任何情况下,也许你改用什么是

public enum JAXBContextFactory {; 

    private static JAXBContext jaxbContext = null; 

    public synchronized static JAXBContext createJAXBContext() throws JAXBException { 
     if (jaxbContext == null) 
      jaxbContext = JAXBContext.newInstance(Customer.class); 
     return jaxbContext; 
    } 

} 
+0

懒惰的初始化是毫无意义的。 –

+0

@ TomHawtin-tackline:这是一个彻底的断言。如果调用代码从来不需要JAXBContext,那么懒惰地初始化它并不是没有意义,事实上这是一个潜在的有用的优化。只要说问题中没有足够的内容来清楚地说出这种或那种方式。 – maerics

+1

@maerics无论如何,类装载是放置的。 –

2

你的方法显然会创建一个新的JAXBContext每次调用时间。

如果你想确保只有一个实例将被创建,不管你的方法被调用多少次,那么你正在寻找Singleton Pattern,实现它会是这个样子:

public class JAXBContextFactory { 
    private static JAXBContext INSTANCE; 
    public static JAXBContext getJAXBContext() throws JAXBException { 
    if (JAXBContextFactory.INSTANCE == null) { 
     INSTANCE = JAXBContext.newInstance(Customer.class); 
    } 
    return INSTANCE; 
    } 
} 

请记住,此实例只对每个Java类加载器唯一。

+1

此实现不同步,可能无法在多线程环境中正常工作。 – LordOfThePigs

+0

@LordOfThePigs在这种情况下创建两个实例似乎并不重要,尽管惰性初始化代码毫无意义。 –

0

分析其他的答案和@汤姆 - hawtin - tackline的意见后,我认为最简单的解决方法是:

public class JAXBContextFactory { 

    private static final JAXBContext CONTEXT = createContext(); 

    private static JAXBContext createContext() { 
     try { 
      return JAXBContext.newInstance(Customer.class); 
     } catch (JAXBException e) { 
      throw new AssertionError(e); 
     } 
    } 

    public static JAXBContext getContext() { return CONTEXT; } 

}