NodeCache
- NodeCache在new对象时候会调用client.newWatcherRemoveCuratorFramework去新建一个监听客户端。
/**
* @param client curztor client
* @param path the full path to the node to cache
* @param dataIsCompressed if true, data in the path is compressed
*/
public NodeCache(CuratorFramework client, String path, boolean dataIsCompressed)
{
this.client = client.newWatcherRemoveCuratorFramework();
this.path = PathUtils.validatePath(path);
this.dataIsCompressed = dataIsCompressed;
}
- start() 启动缓存服务
public void start(boolean buildInitial) throws Exception
{
//设值启动状态
Preconditions.checkState(state.compareAndSet(State.LATENT, State.STARTED), "Cannot be started more than once");
//增加连接状态监听 client.getConnectionStateListenable().addListener(connectionStateListener);
// 进行初始化操作
if ( buildInitial )
{
client.checkExists().creatingParentContainersIfNeeded().forPath(path);
internalRebuild();
}
reset();
}
// 判断是否是启动连接状态,判断节点是否存在
private void reset() throws Exception
{
if ( (state.get() == State.STARTED) && isConnected.get() )
{
client.checkExists().creatingParentContainersIfNeeded().usingWatcher(watcher).inBackground(backgroundCallback).forPath(path);
}
}
在reset()方法中传入了两个对象,一个监听对象watcher,一个是回调对象backgroundCallback(异步回调)
刚开始启动会注册一个watcher对象,当服务器返回数据回来时候会调用回调函数
private void processBackgroundResult(CuratorEvent event) throws Exception
{
// 当发生获取数据或者是判断节点是否存在时候进行监听
switch ( event.getType() )
{
case GET_DATA:
// 响应状态为ok时,将刷新本地缓存的数据
if ( event.getResultCode() == KeeperException.Code.OK.intValue() )
{ // 获取监听到的数据变动集合
ChildData childData = new ChildData(path, event.getStat(), event.getData());
// 刷新本地缓存数据
setNewData(childData);
}
break;
}
case EXISTS:
{
if ( event.getResultCode() == KeeperException.Code.NONODE.intValue() )
{
setNewData(null);
}
else if ( event.getResultCode() == KeeperException.Code.OK.intValue() )
{
if ( dataIsCompressed )
{
client.getData().decompressed().usingWatcher(watcher).inBackground(backgroundCallback).forPath(path);
}
else
{
client.getData().usingWatcher(watcher).inBackground(backgroundCallback).forPath(path);
}
}
break;
}
}
刷新本地缓存数据,触发监听
//private final ListenerContainer<NodeCacheListener> listeners 监听容器集合
private void setNewData(ChildData newData) throws InterruptedException
{
// data 缓存对象,getAndSet 设置新值并返回旧值
ChildData previousData = data.getAndSet(newData);
// 两个对象不一致时,触发监听
if ( !Objects.equal(previousData, newData) )
{
// 将本地的监听容器循环
listeners.forEach
( // 将监听对象作为参数传入给foreach方法,之后方法里会调用
new Function<NodeCacheListener, Void>()
{
@Override
public Void apply(NodeCacheListener listener)
{
try
{
listener.nodeChanged();
}
catch ( Exception e )
{
ThreadUtils.checkInterrupted(e);
log.error("Calling listener", e);
}
return null;
}
}
);
if ( rebuildTestExchanger != null )
{
try
{
rebuildTestExchanger.exchange(new Object());
}
catch ( InterruptedException e )
{
Thread.currentThread().interrupt();
}
}
}
}
//接口方法Function<F,T> F是参数 T是返回值
@GwtCompatible
public interface Function<F, T> {
@Nullable
@CanIgnoreReturnValue
T apply(@Nullable F var1);
boolean equals(@Nullable Object var1);
}
// ListenerContainer 监听容器里foreach方法,循环调用每一个监听器
/**
* Utility - apply the given function to each listener. The function receives
* the listener as an argument.
*
* @param function function to call for each listener
*/
public void forEach(final Function<T, Void> function)
{
for ( final ListenerEntry<T> entry : listeners.values() )
{
entry.executor.execute
(
new Runnable()
{
@Override
public void run()
{
try
{
function.apply(entry.listener);
}
catch ( Throwable e )
{
ThreadUtils.checkInterrupted(e);
log.error(String.format("Listener (%s) threw an exception", entry.listener), e);
}
}
}
);
}
}