Java 如何创建和稍后访问应用程序级资源?
编辑:我正在尝试为web应用程序的所有会话创建共享数据库连接池。另一篇帖子说,创建servlet上下文对象的最佳方法是让init侦听器创建它。但是,我不清楚如何使此对象可供我的servlet使用。一个解决方案是使用私有持有者类:Java 如何创建和稍后访问应用程序级资源?,java,servlets,web-applications,servletcontextlistener,shared-resource,Java,Servlets,Web Applications,Servletcontextlistener,Shared Resource,编辑:我正在尝试为web应用程序的所有会话创建共享数据库连接池。另一篇帖子说,创建servlet上下文对象的最佳方法是让init侦听器创建它。但是,我不清楚如何使此对象可供我的servlet使用。一个解决方案是使用私有持有者类: public class SomeClass { private static class ResourceHolder { private static final Resource INSTANCE = new Resource();
public class SomeClass {
private static class ResourceHolder {
private static final Resource INSTANCE = new Resource();
}
public static Resource getInstance() {
return ResourceHolder.INSTANCE;
}
}
第一次调用
SomeClass.getInstance()
时,将初始化实例。一种解决方案是使用私有holder类:
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
}
}
使用类加载器加载类后,这将初始化
内容
数组。另一种方法是使用静态初始化:
public class SomeClass {
private static final Object[] CONTENT;
static {
CONTENT = new Object[SomeOtherClass.getContentSize()]; // To show you can access runtime variables
}
}
使用类加载器加载类后,这将初始化内容数组。类似于:
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>();
}
};
公共静态抽象类{
私有T=null;
无法获取公共数据(){
如果(t==null){
t=创建();
}
返回t;
}
受保护的抽象T create();
}
public static final Lazy lazyList=new Lazy(){
@凌驾
受保护列表创建(){
返回新的ArrayList();
}
};
类似于:
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>();
}
};
公共静态抽象类{
私有T=null;
无法获取公共数据(){
如果(t==null){
t=创建();
}
返回t;
}
受保护的抽象T create();
}
public static final Lazy lazyList=new Lazy(){
@凌驾
受保护列表创建(){
返回新的ArrayList();
}
};
首先我要提醒您,您所描述的内容有一点代码味道,我想您最好完全避免这种模式。依赖于外部运行时状态的静态资源打破了关于变量范围的各种最佳实践
然而,您所描述的最好由a或a实现,这取决于成功构建所需对象所涉及的工作。这种差异有点迂腐,但您通常会使用未来
来保存需要很长时间计算的引用,而供应商
通常会很快返回Future
还与Java的并发实用程序进行了一些很好的挂钩,但听上去您并不需要这些
您可以使用供应商
,如下所示:
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
}
});
...
}
公共类全局状态{
公共静态最终供应商MY_数据=Suppliers.memoize(
新供应商(){
公共懒散数据获取(){
//构造对象需要做什么,只在需要时执行一次
}
});
...
}
将以线程安全的方式缓存对底层供应商的第一次调用的结果,因此只需使用此调用包装您定义的供应商
,即可防止重复处理。我会提前提醒您,您描述的内容有一点代码味道,我想你最好完全避免这种模式。依赖于外部运行时状态的静态资源打破了关于变量范围的各种最佳实践
然而,您所描述的最好由a或a实现,这取决于成功构建所需对象所涉及的工作。这种差异有点迂腐,但您通常会使用未来
来保存需要很长时间计算的引用,而供应商
通常会很快返回Future
还与Java的并发实用程序进行了一些很好的挂钩,但听上去您并不需要这些
您可以使用供应商
,如下所示:
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
}
});
...
}
公共类全局状态{
公共静态最终供应商MY_数据=Suppliers.memoize(
新供应商(){
公共懒散数据获取(){
//构造对象需要做什么,只在需要时执行一次
}
});
...
}
将以线程安全的方式缓存对底层供应商的第一次调用的结果,因此只需将用此调用定义的供应商
包装即可防止重复处理。最简单的延迟初始化是对一个实例使用枚举
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.
}
}
注意:这是线程安全的,因为静态块初始化是安全的。最简单的延迟初始化是对一个实例使用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.
}
}
注意:这是线程安全的,因为静态块初始化是安全的。您能给我们一些代码来解释您的问题吗?您不能使用空构造函数吗?然后检查字段是否已初始化?最后一点是什么?请StackOverflow上的人为您编写初始化代码。您能给我们一些代码来帮助解释您的问题吗?您不能使用空构造函数吗?然后检查字段是否已初始化?最后一点是什么?请StackOverflow上的人为您编写初始化代码。这称为模式。它干净且线程安全,但确实会产生难以测试和模块化的代码。因此,应该谨慎使用它。是否可以像我说的那样延迟初始化此模式,我无权访问在加载时创建此对象所需的参数。@user3056052是否有需要它的原因?它是一个数据库连接?静态的,因为db连接是一个有限的资源;最终的,因为我不想在建立连接后更改它。至于我为什么不硬编码,请注意