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);
}
}
}
);
}
}