Как вы создаете и позже получаете доступ к ресурсу уровня приложения?

Изменить: я пытаюсь создать общий пул соединений с базой данных для всех сеансов веб-приложения. В другом сообщении говорилось, что лучший способ создать объект контекста сервлета — создать его с помощью прослушивателя инициализации. Однако я не понимаю, как сделать этот объект доступным для использования моим сервлетом.


person user3056052    schedule 17.01.2014    source источник
comment
Можете ли вы дать нам код, который может помочь объяснить вашу проблему?   -  person Keppil    schedule 17.01.2014
comment
Разве вы не можете использовать пустой конструктор? А затем проверьте поля, чтобы узнать, было ли оно инициализировано? а смысл финала?   -  person Sherif elKhatib    schedule 17.01.2014
comment
Попросите кого-нибудь на StackOverflow написать для вас код инициализации.   -  person Hot Licks    schedule 17.01.2014


Ответы (5)


Другой способ сделать это - использовать статическую инициализацию:

public class SomeClass {

    private static final Object[] CONTENT;

    static {
        CONTENT = new Object[SomeOtherClass.getContentSize()]; // To show you can access runtime variables
    }

}

Это инициализирует массив CONTENT после загрузки класса с помощью ClassLoader.

person Obicere    schedule 17.01.2014

Одним из решений является использование класса частного владельца:

public class SomeClass {
    private static class ResourceHolder {
        private static final Resource INSTANCE = new Resource();
    }

    public static Resource getInstance() { 
        return ResourceHolder.INSTANCE;
    }
}

экземпляр будет инициализирован при первом вызове SomeClass.getInstance().

person assylias    schedule 17.01.2014
comment
Это называется шаблоном Singleton Holder. Он чистый и потокобезопасный, но делает код трудным для тестирования и модульности. Поэтому его следует использовать с осторожностью. - person dimo414; 17.01.2014
comment
можно ли лениво инициализировать этот шаблон, как я сказал, у меня нет доступа к аргументам, необходимым для создания этого объекта при загрузке. - person user3056052; 17.01.2014
comment
@ user3056052 Есть ли причина, по которой вам нужен статический финал? - person assylias; 17.01.2014
comment
это подключение к базе данных? static, потому что соединения с базой данных являются ограниченным ресурсом, final, потому что я не хочу, чтобы он менялся после установления соединения. Что касается того, почему я не жестко кодирую это, потому что мне нужно вытащить URL-адрес и учетные данные из файла web.xml. - person user3056052; 17.01.2014
comment
@user3056052 user3056052 Я бы вообще так не поступил. Вы должны инициализировать один пул подключений в начале своего основного с соответствующими настройками и передать его всем, кто в нем нуждается, вместо того, чтобы иметь глобальную переменную где-то в вашем коде. - person assylias; 17.01.2014
comment
@assylias, ты помог мне пойти по правильному пути, хотя у меня нет главного, это сервлет. Теперь я сохраняю соединение в сеансе и создаю его только в том случае, если в моем сеансе он не определен. Может быть, есть лучший способ? - person user3056052; 17.01.2014
comment
@user3056052 user3056052 Я не очень хорошо разбираюсь в сервлетах. Если вы сомневаетесь, вам следует задать более конкретный вопрос, объясняющий, чего вы пытаетесь достичь - я почти уверен, что есть стандартный способ сделать это, и синглтон, даже если он может работать, вероятно, не лучший способ. - person assylias; 17.01.2014
comment
@user3056052 user3056052 Было задано много вопросов и ответов о правильной настройке и совместном использовании подключений к базе данных. Рассмотрим stackoverflow.com/questions/241454/ и google. com/search?q=servlet%20database%20connection - person dimo414; 18.01.2014

Самая простая ленивая инициализация — использовать enum с одним экземпляром.

enum Singleton {
    INSTANCE; // lazy initialised
}

Дополнительная проблема заключается в том, что вам нужны значения инициализации. Чтобы справиться с этим, вы можете вложить класс.

enum Utility {;
     static MyType val;
     static OtherType val2;

     enum Holder {
         INSTANCE;

         Holder() {
            // uses val and val2
         }
     }

     public static Holder getInstance(MyType val, OtherType val2) {
         Utility.val = val;
         Utility.val2 = val2;
         return Holder.INSTANCE; // only created the first time.
     }
 }

Примечание: это потокобезопасно, так как инициализация статического блока безопасна.

person Peter Lawrey    schedule 17.01.2014

Что-то вроде:

public static abstract class Lazy<T> {

    private T t = null;

    public synchronized T get() {
        if (t == null) {
            t = create();
        }
        return t;
    }

    protected abstract T create();
}

public static final Lazy<List<String>> lazyList = new Lazy<List<String>>(){

    @Override
    protected List<String> create() {
        return new ArrayList<String>();
    }
}; 
person Tom    schedule 17.01.2014

Я сразу предупрежу вас, что то, что вы описываете, имеет немного запаха кода, и я подозреваю, что вам лучше полностью избегать этого шаблона. Статический ресурс, зависящий от внешнего состояния среды выполнения, нарушает все передовые методы работы с областью видимости переменных.


Однако то, что вы описываете, лучше всего реализовать с помощью Supplier или Future, в зависимости от объема работы, необходимого для успешного создания нужного вам объекта. Разница несколько педантична, но вы обычно используете Future для хранения ссылки, которая займет много времени для вычисления, в то время как Supplier обычно возвращает быстро. Future также имеет несколько хороших подключений к утилитам параллелизма Java, но, судя по всему, вам это не нужно.

Вы бы использовали Supplier так:

public class GlobalState {
  public static final Supplier<LazyData> MY_DATA = Suppliers.memoize(
    new Supplier<LazyData>() {
      public LazyData get() {
        // do whatever you need to construct your object, only gets executed once needed
      }
    });

  ...
}

Suppliers.memoize() будет кэшировать результат первого вызова базового Supplier потокобезопасным способом, поэтому простое обертывание Supplier, которое вы определяете с помощью этого вызова, предотвращает дублирование обработки.

person dimo414    schedule 17.01.2014