Как создать и впоследствии получить доступ к ресурсу уровня приложения?
Изменить: я пытаюсь создать пул соединений с общей базой данных для всех сеансов веб-приложения. В другом посте говорилось, что лучший способ создать объект контекста сервлета - создать его для прослушивателя init. Однако мне неясно, как сделать этот объект доступным для использования моим сервлетом.
5 ответов
Другой способ сделать это - использовать статическую инициализацию:
public class SomeClass {
private static final Object[] CONTENT;
static {
CONTENT = new Object[SomeOtherClass.getContentSize()]; // To show you can access runtime variables
}
}
Это будет инициализировать CONTENT
массив после загрузки класса с использованием ClassLoader.
Одним из решений является использование класса частного владельца:
public class SomeClass {
private static class ResourceHolder {
private static final Resource INSTANCE = new Resource();
}
public static Resource getInstance() {
return ResourceHolder.INSTANCE;
}
}
экземпляр будет инициализирован, когда SomeClass.getInstance()
называется первый раз.
Простейшая ленивая инициализация - использовать 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.
}
}
Примечание: это потокобезопасно, так как инициализация статического блока безопасна.
Я предупреждаю вас заранее, то, что вы описываете, имеет некоторый запах кода, и я подозреваю, что вы сделаете лучше, чтобы полностью избежать этого паттерна. Статический ресурс, который зависит от внешнего состояния среды выполнения, нарушает все виды передовых методов работы с переменной областью.
Однако то, что вы описываете, лучше всего реализовать 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
Вы определяете с помощью этого вызова предотвращает дублирование обработки.
Что-то вроде:
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>();
}
};