【发布时间】:2017-12-08 01:51:49
【问题描述】:
我正在尝试为 Java SE 控制台应用程序设置 JNDI。
我有以下代码:
public class FooMain {
public static void main (String args[]) throws NamingException {
Context context = new InitialContext();
context.bind("foo", "bar");
}
}
…而上下文工厂定义为:
public class MyContextFactory implements InitialContextFactory {
private static Hashtable store = new Hashtable();
@Override
public Context getInitialContext(Hashtable environment) throws NamingException {
return new InitialContext() {
@Override
public void bind(String name, Object obj) {
store.put(name, obj);
}
@Override
public Object lookup(String name) {
return store.get(name);
}
};
}
}
当我使用 FooMain 类调用时:
java -Djava.naming.factory.initial=MyContextFactory -cp ... FooMain
我得到无限递归和最终的 StackOverflow 异常:
Exception in thread "main" java.lang.StackOverflowError
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.naming.internal.VersionHelper12.getContextClassLoader(VersionHelper12.java:185)
at com.sun.naming.internal.ResourceManager.getApplicationResources(ResourceManager.java:549)
at com.sun.naming.internal.ResourceManager.getInitialEnvironment(ResourceManager.java:244)
at javax.naming.InitialContext.init(InitialContext.java:240)
at javax.naming.InitialContext.<init>(InitialContext.java:192)
at MyContextFactory$1.<init>(MyContextFactory.java:20)
at MyContextFactory.getInitialContext(MyContextFactory.java:20)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:684)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
at javax.naming.InitialContext.init(InitialContext.java:244)
at javax.naming.InitialContext.<init>(InitialContext.java:192)
at MyContextFactory$1.<init>(MyContextFactory.java:20)
at MyContextFactory.getInitialContext(MyContextFactory.java:20)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:684)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
at javax.naming.InitialContext.init(InitialContext.java:244)
at javax.naming.InitialContext.<init>(InitialContext.java:192)
at MyContextFactory$1.<init>(MyContextFactory.java:20)
at MyContextFactory.getInitialContext(MyContextFactory.java:20)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:684)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
at javax.naming.InitialContext.init(InitialContext.java:244)
at javax.naming.InitialContext.<init>(InitialContext.java:192)
...
我可以通过创建一个“环境”哈希表,将MyContextFactory 类的名称放在那里(在“java.naming.factory.initial”键下),然后使用创建InitialContext接受 Hashtable 环境的构造函数:
Context context = new InitialContext(environment);
但我的问题是:如何使用无参数构造函数完成这项工作,并在调用 JVM 时使用“-Djava.naming.factory.initial”提供工厂类的名称?
【问题讨论】:
-
这是一个有趣的问题。
InitialContext确实是Context的包装器,它知道在其构造函数中查找自定义工厂并使用它。当您在 JVM 启动之前替换工厂时,您会得到递归,因为默认工厂永远不会被使用。不知道如何解决这个问题,但我怀疑这将涉及读取 InitialContext 的代码并在默认值未运行时覆盖其某些行为。 -
一个建议的调查途径:你可能无法使用匿名内部类,因为我相信你需要使用
InitialContext的惰性初始化构造函数。 -
是的,做到了。
-
请写下您的解决方案,将其作为答案发布,然后在所需的等待期后接受您的答案。这是一个有用的问题,可能会在未来帮助其他人(这是 SO 的重点)。