편집 : 웹 응용 프로그램의 모든 세션에 대해 공유 데이터베이스 연결 풀을 만들려고합니다. 다른 포스트는 서블릿 컨텍스트 객체를 생성하는 가장 좋은 방법은 init 리스너가 생성하는 것이 었습니다. 그러나이 객체를 내 서블릿에서 사용할 수 있도록 만드는 방법에 대해서는 분명하지 않습니다.응용 프로그램 수준 리소스를 만들고 나중에 액세스하려면 어떻게합니까?
답변
하나 개의 솔루션은 전용 홀더 클래스를 사용하고 있습니다 :
public class SomeClass {
private static class ResourceHolder {
private static final Resource INSTANCE = new Resource();
}
public static Resource getInstance() {
return ResourceHolder.INSTANCE;
}
}
인스턴스가 SomeClass.getInstance()
가 처음으로 호출 될 때 초기화됩니다. 클래스가 클래스 로더를 사용하여로드되면
public class SomeClass {
private static final Object[] CONTENT;
static {
CONTENT = new Object[SomeOtherClass.getContentSize()]; // To show you can access runtime variables
}
}
이는 CONTENT
배열을 초기화합니다 : 당신이 할 수있는
[Singleton Holder] (http://en.wikipedia.org/wiki/Singleton_pattern#Initialization_On_Demand_Holder_Idiom) 패턴이라고합니다. 그것은 깨끗하고 threadsafe하지만, 테스트 및 모듈화가 어려운 코드를 만듭니다. 따라서주의해서 사용해야합니다. – dimo414
로드 할 때이 객체를 만드는 데 필요한 인수에 액세스 할 수 없다고 말한 것처럼이 패턴을 초기화하는 것이 지연 될 수 있습니다. – user3056052
@ user3056052 static final이 필요한 이유가 있습니까? – assylias
또 다른 방법은 정적 초기화를 사용합니다. 같은
뭔가 :
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>();
}
};
내가 정면을주의 것은, 당신이 설명하는 것은 코드 냄새의 비트를 가지고 있으며, 당신이 완전히이 패턴을 피하기 위해 더 잘 할 것이다 생각한다. 외부 런타임 상태에 의존하는 정적 리소스는 가변 범위에 대한 모든 종류의 베스트 프랙티스를 손상시킵니다.
당신은, 그러나, 최고의 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
에 대한 첫 번째 호출의 결과를 캐시합니다 중복을 방지 처리.
가장 간단한 게으른 초기화는 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.
}
}
참고 : 정적 블록 초기화가 안전하므로 스레드로부터 안전합니다.
문제를 설명하는 데 도움이되는 몇 가지 코드를 제공해 주시겠습니까? – Keppil
빈 생성자를 사용할 수 없습니까? 그런 다음 필드가 초기화되었는지 확인하십시오. 그래도 마지막 지점은 뭐니? –
StackOverflow의 누군가에게 초기화 코드를 작성하도록 요청하십시오. –