将昂贵的资源创建放在静态块中



我正在使用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代码放在静态方法下,如上所示。

现在,每当JAXBContextFactory.createJAXBContext();需要引用JAXBContex时,请求都会调用它。现在我的问题是,在这种情况下,JAXBContext只创建一次还是应用程序会有多个JAXBContext实例?

每次调用此方法时,应用程序将有一个 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 实例(保证只存在一次)。在实现中,您不会将刚刚创建的实例保存在任何地方,并且每次调用该方法时只会创建一个新实例。重要提示:不要忘记添加到方法声明中的 synchronized 关键字,因为它可确保在多线程环境中调用此方法仍将按预期工作。

您的实现将为它的每个请求创建一个新的 JAXBContext。相反,您可以执行以下操作:

public class JAXBContextFactory {
    private static JAXBContext jaxbContext;
    static {
        try {
            jaxbContext = JAXBContext.newInstance(Customer.class);
        } catch (JAXBException ignored) {
        }
    }
    public static JAXBContext createJAXBContext() {
        return jaxbContext;
    }
}

您的方法将在每次调用时清楚地创建一个新的 JAXBContext。

如果要确保只创建一个实例,而不管调用方法多少次,那么您正在寻找单例模式,其实现如下所示:

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 类装入器中是唯一的。

每次调用该方法时,您都有一个实例。使用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;
    }
}

在分析了其他答案和@tom-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; }
}

最新更新