2012-06-13 1 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 под статическим методом, как показано выше.

Теперь запросы будут называть JAXBContextFactory.createJAXBContext(); всякий раз, когда ему нужна ссылка на JAXBContex. Теперь мой вопрос: в этом случае JAXBContext создается только один раз или приложение имеет несколько экземпляров JAXBContext?

+1

Посмотрите на дизайн синглтон шаблон. 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

Проанализировав другие ответы и @ том- Хотин-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; } 

} 
Смежные вопросы