最近在OC4J 10g引用了weblogic10的jar包时,发现Local对象无法获取,总是报javax.naming.NameNotFoundException,于是分析了一下context.lookup是如何执行的。
在获取Local bean时,所用语句如下:
final InitialContext context = new InitialContext();
String jndiName = "java:comp/env/ejb/BusinessLocal";
Object object = context.lookup(jndiName );
解析new InitialContext();
new InitialContext()à
myProps = ResourceManager.getInitialEnvironment(environment); à
String[] jndiSysProps = helper.getJndiProperties();à
System.getProperties();
myProps的值为:
{java.naming.factory.initial=com.evermind.server.ApplicationInitialContextFactory,
java.naming.factory.url.pkgs=oracle.oc4j.naming.url:weblogic.jndi.factories:weblogic.corba.j2ee.naming.url}
解析context.lookup(jndiName );
context.lookup(jndiName ) à
context.getURLOrDefaultInitCtx(String name); à
NamingManager.getURLContext(scheme, myProps); à
NamingManager.getURLObject(scheme, null, null, null, environment); à
ResourceManager.getFactory(
Context.URL_PKG_PREFIXES, environment, nameCtx,
"."+scheme+"."+scheme+"URLContextFactory",defaultPkgPrefix);
分析ResourceManager.getFactory()源码
public static Object getFactory(String propName, Hashtable env,
Context ctx, String classSuffix, String defaultPkgPrefix)
throws NamingException {
// Merge property with provider property and supplied default
//从env获取java.naming.factory.url.pkgs的值
String facProp = getProperty(propName, env, ctx, true);
if (facProp != null)
facProp += (":" + defaultPkgPrefix); //注意在此时加上了默认的sun的com.sun.jndi.url
else
facProp = defaultPkgPrefix;
// Cache factory based on context class loader, class name, and
// property val
ClassLoader loader = helper.getContextClassLoader(); //此时loader为simple.root:0.0.0
String key = classSuffix + " " + facProp;
Map perLoaderCache = null;
synchronized (urlFactoryCache) {
perLoaderCache = (Map) urlFactoryCache.get(loader);
if (perLoaderCache == null) {//第一次perLoaderCache为null
perLoaderCache = new HashMap(11);
urlFactoryCache.put(loader, perLoaderCache);
}
}
synchronized (perLoaderCache) {
Object factory = null;
WeakReference factoryRef = (WeakReference) perLoaderCache.get(key);
if (factoryRef == NO_FACTORY) {
return null;
} else if (factoryRef != null) {//第一次factoryRef为null
factory = factoryRef.get();
if (factory != null) { // check if weak ref has been cleared
return factory;
}
}
// Not cached; find first factory and cache
StringTokenizer parser = new StringTokenizer(facProp, ":");
String className;
while (factory == null && parser.hasMoreTokens()) {
className = parser.nextToken() + classSuffix;
/* 这里className 的值分别为
oracle.oc4j.naming.url.java.javaURLContextFactory
weblogic.jndi.factories.java.javaURLContextFactory
weblogic.corba.j2ee.naming.url.java.javaURLContextFactory
com.sun.jndi.url.java.javaURLContextFactory */
try {
// System.out.println("loading " + className);
factory = helper.loadClass(className, loader).newInstance();
} catch (InstantiationException e) {
//略
} catch (IllegalAccessException e) {
//略
} catch (Exception e) {
// ignore ClassNotFoundException, IllegalArgumentException,
// etc.
}
}
// Cache it.
perLoaderCache.put(key, (factory != null) ? new WeakReference(
factory) : NO_FACTORY);
return factory;
}
}
最后factory.getObjectInstance(urlInfo, name, nameCtx, environment);
当不加载weblogic的jar包时,
java.naming.factory.url.pkgs=oracle.oc4j.naming.url;
当className=oracle.oc4j.naming.url.java.javaURLContextFactory,返回的factory=null,所以最终使用的Factory是com.sun.jndi.url.java.javaURLContextFactory,这个时候没有问题;
当加载weblogic的jar包时,
java.naming.factory.url.pkgs=
oracle.oc4j.naming.url:
weblogic.jndi.factories:
weblogic.corba.j2ee.naming.url
使用的Factory是
weblogic.jndi.factories.java.javaURLContextFactory
而在获取Local bean时抛出javax.naming.NameNotFoundException。