服务定义及启动
<mbean code="org.jboss.naming.NamingService"
name="jboss:service=Naming"
xmbean-dd="resource:xmdesc/NamingService-xmbean.xml">
<attribute name="CallByValue">false</attribute>
<attribute name="Port">1099</attribute>
<attribute name="BindAddress">${jboss.bind.address}</attribute>
<attribute name="RmiPort">1098</attribute>
<attribute name="RmiBindAddress">${jboss.bind.address}</attribute>
<depends optional-attribute-name="LookupPool" proxy-type="attribute">jboss.system:service=ThreadPool</depends>
</mbean>
NamingService
// 构造函数 NamingService()
naming = new Main(this.getClass().getName());
Main是一个jnp名字服务的实现.
// 请关注,proxyFactory(JRMPProxyFactoryMBean)
// 启动服务 startService()
naming.start();
bind ObjectFactory to "java:comp"
Main.start()
// 构造NamingServer, NamingServer是JNDI名字服务的实现.
theServer = new NamingServer();
// initCustomSockFactories()
// initJnpInvoker(), 创建NamingServer的服务Stub.
Remote stub = UnicastRemoteObject.exportObject(theServer, ...);
serverStub = new MarshalledObject(stub);
// initBootstrapListencer()
启动一个AcceptHandler线程开始listen, 输出serverStub;
NamingServer为jbossns的核心实现类, 它保存着所有注册的组件,组件的存储结构为树状的。
InitialContext是客户端访问JNDI的入口,它通过给定的properties值进行初始化,它可以连接到本地(同一JVM)或者远程的JNDI上,典型的初始化代码如下:
Properties props = new Properties();
props.put("java.naming.factory.initial", "...");
props.put("java.naming.factory.url.pkgs", "...");
props.put("java.naming.provider.url", "jnp://...");
InitialContext initCtx = new InitialContext(props);
在InitialContext中有一个getDefaultInitCtx方法,它根据java.naming.factory.initial的值来创建Context.
// initialContext.java
protected Context getDefaultInitCtx() throws NamingException{
if (!gotDefault) {
defaultInitCtx = NamingManager.getInitialContext(myProps);
gotDefault = true;
}
return defaultInitCtx;
}
NamingContextFactory实现了InitialContextFactory接口(必须).
// org.jnp.interfaces.NamingContextFactory
public Context getInitialContext(Hashtable env)
throws NamingException {
String providerURL = (String) env.get(Context.PROVIDER_URL);
Name prefix = null;
int comma = providerURL != null ? providerURL.indexOf(',') : -1;
if( providerURL != null && comma < 0 ) {
// 处理prefix
}
return new NamingContext(env, prefix, null);
}
这里返回一个NamingContext, 它是Context的实现类,对InitialContext的一些操作都将转发给它,如lookup, bind和unbind等操作。
NamingContext在JBossNS中是一个客户端的角色,它与服务端进行通信并得到一个NamingServer的stub,
static Naming getServer(String host, int port,
Hashtable serverEnv)
throws NamingException {
// step 1.
SocketFactory factory = loadSocketFactory(serverEnv);
Socket s;
// parse localAddr, localPort
// ...
// step 2.
s = factory.createSocket(host, port, localAddr, localPort);
// Get stub from naming server
// step 3.
BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
ObjectInputStream in = new ObjectInputStream(bis);
MarshalledObject stub = (MarshalledObject) in.readObject();
server = (Naming) stub.get();
s.close();
return server;
}
首先装载SocketFactory的实现类,然后解析localAddr和localPort并创建客户端socket与服务端进行通信,还记得前面的initBootstrapListencer吗?这里创建的socket就是与initBootstrapListencer创建的服务端socket进行连接.
最后我们就得到了一个NameingServer的stub.
[jbossns 关系图]