当调用ApplicationAdapter的public boolean createSharedObject(IScope scope, String name, boolean persistent)方法时,就在scope下创建了一个名为name的共享对象。它又调用ISharedObjectService的createSharedObject方法。ISharedObjectService是在red5-common.xml中注入的,默认是org.red5.server.so.SharedObjectService。它的创建方法是:
1: /** {@inheritDoc} */ 2: public boolean createSharedObject(IScope scope, String name, boolean persistent) { 3: if (hasSharedObject(scope, name)) { 4: // The shared object already exists.
5: return true;
6: }
7: synchronized (scope) { 8: final IBasicScope soScope = new SharedObjectScope(scope, name, persistent, getStore(scope, persistent));
9: return scope.addChildScope(soScope);
10: }
11: }
可以看到创建共享对象其实就是new了一个SharedObjectScope,它继承了BaseScope,实现了ISharedObject接口。
1: public class SharedObjectScope extends BasicScope implements ISharedObject, StatusCodes
通过ApplicationAdapter的getSharedObject方法获取共享对象其实就是SharedObjectScope这个Scope!它有一个SharedObject成员,它负责存取具体的共享对象属性值。SharedObject并没有实现ISharedObject,我们平常操作的共享对象是ISharedObject(其实就是SharedObjectScope这个Scope),并非SharedObject对象。
当有客户端连接名为name的共享对象时,如果没有则调用ISharedObjectService的createSharedObject方法创建一个名为name的共享对象(scope)。
客户端断开共享对象的连接,其实就是断开共享对象这个scope的连接!客户端发起断开共享对象的连接的事件时,RTMPHandler监听到SharedObject事件,进入onSharedObject处理函数。将共享对象消息分派给SharedObjectScope(实现ISharedObject接口)的dispatchEvent处理,根据消息的类型(SERVER_DISCONNECT)要么从rtmp连接中注销这个Scope(unregisterBasicScope),要么removeEventListener。
1: public void unregisterBasicScope(IBasicScope basicScope) {2: basicScopes.remove(basicScope);
3: basicScope.removeEventListener(this);
4: }
它依然走了SharedObjectScope的removeEventListener方法。
1: @Override
2: public void removeEventListener(IEventListener listener) { 3: so.unregister(listener);
4: //part 1 of the fix for TRAC #360 - if we have not been released by all that acquired then
5: //keep on disconnection of the last listener
6: if (so.isAcquired()) { 7: keepOnDisconnect = true;
8: }
9: //remove the listener
10: super.removeEventListener(listener);
11: //part 2 of the fix for TRAC #360 - check acquire
12: if (!so.isPersistentObject() && (so.getListeners() == null || so.getListeners().isEmpty()) && !so.isAcquired()) {13: getParent().removeChildScope(this);
14: }
15:
16: for (ISharedObjectListener soListener : serverListeners) {17: soListener.onSharedObjectDisconnect(this);
18: }
19: }
so.unregister中
1: protected void unregister(IEventListener listener) {2: listeners.remove(listener);
3: listenerStats.decrement();
4: checkRelease();
5: }
调用了checkRelease()方法:
1: /**
2: * Check if shared object must be released.
3: */
4: protected void checkRelease() { 5: //part 3 of fix for TRAC #360
6: if (!isPersistentObject() && listeners.isEmpty() && !isAcquired()) { 7: log.info("Deleting shared object {} because all clients disconnected and it is no longer acquired.", name); 8: if (storage != null) { 9: if (!storage.remove(this)) {10: log.error("Could not remove shared object.");11: }
12: }
13: close();
14: }
15: }
看到了吗“Deleting shared object {} because all clients disconnected and it is no longer acquired.”,。在close中删除了共享对象的所有属性。再回到removeEventListener中:
1: if (!so.isPersistentObject() && (so.getListeners() == null || so.getListeners().isEmpty()) && !so.isAcquired()) {2: getParent().removeChildScope(this);
3: }
这里将SharedObjectScope这个Scope删掉了。
客户端再次连到这个共享对象时,如果没有则再次创建:
1: if (!sharedObjectService.createSharedObject(scope, name, persistent)) {2: sendSOCreationFailed(conn, name, persistent);
3: return;
4: }
如果你的应用希望没有客户端连接时仍然保持着共享对象,可以通过checkRelease函数找解决办法——checkRelease有如下判断:
隐藏行号 复制代码 ? 这是一段程序代码。
if (!isPersistentObject() && listeners.isEmpty() && !isAcquired())
只有当该共享对象不是持久化的且没有客户端监听且没有获取(acquireCount=0)时,才走close清空共享对象。所以要想满足不清空的需求,要么让其持久化,要么监听不为空,要么acquireCount>0。对于非持久化的共享对象。系统调用
一下,就能保证所有客户端断开共享对象时acquireCount仍然大于0。以后需要释放的时候调用:
即可。
release函数源代码:
隐藏行号 复制代码 ? 这是一段程序代码。
public void release() {
if (acquireCount.get() == 0) {
throw new RuntimeException("The shared object was not acquired before.");
}
if (acquireCount.decrementAndGet() == 0) {
checkRelease();
}
}
当前acquireCount==0时调用release将会抛异常,提示“The shared object was not acquired before.”。