1

编辑:我正在尝试为Web应用程序的所有会话创建共享数据库连接池。另一篇文章说,创建Servlet上下文对象的最佳方式是让init侦听器创建它。然而我不清楚如何让这个对象可供我的servlet使用。您如何创建和以后访问应用程序级资源?

+1

你能不能给我们一些代码,这可能有助于解释你的问题? – Keppil

+1

你不能使用空的构造函数吗?然后检查字段以了解它是否已被初始化?最后的意义何在? –

+0

请求StackOverflow上的某个人为您编写初始化代码。 –

回答

2

一种解决方案是使用专用支架类:

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

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

SomeClass.getInstance()被称为第一次实例将被初始化。

+0

这被称为[辛格尔顿持有人(http://en.wikipedia.org/wiki/Singleton_pattern#Initialization_On_Demand_Holder_Idiom)图案。它很干净且线程安全,但确实使代码难以测试和模块化。因此应谨慎使用。 – dimo414

+0

是否可以延迟初始化这种模式,就像我说我无法访问在加载时创建此对象所需的参数。 – user3056052

+0

@ user3056052有没有理由你需要它静态最终? – assylias

2

你可以做到这一点的另一种方法是使用静态初始化:

public class SomeClass { 

    private static final Object[] CONTENT; 

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

} 

一旦类是使用类装入器装入这将初始化CONTENT阵列。

0

喜欢的东西:

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>(); 
    } 
}; 
0

我会提醒你前面,你要描述有位代码的气味,我怀疑你会做的更好,以完全避免了这种模式。依赖外部运行时状态的静态资源打破了有关变量范围的各种最佳实践。


你所描述的,但是,将最被无论是SupplierFuture实现什么,这取决于所涉及的成功构建你所需要的对象的工作。所不同的是有些迂腐,但你通常会使用一个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给您的通话定义防止重复处理。

1

最简单的懒初始化是使用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. 
    } 
} 

注意:这是线程安全的,因为静态块初始化是安全的。