接口實現
public void addListener(Object listener) { //interface 1
synchronized (lock) {
if (allListeners.add(listener)) {
for (BroadcastDispatch<?> broadcaster : dispatchers.values()) {
maybeAddToDispatcher(broadcaster, listener);
}
}
}
}
------------------------------------------------------------------------------
public void useLogger(Object logger) { //interface 2
synchronized (lock) {
if (allLoggers.add(logger)) {
for (LoggerDispatch dispatch : loggers.values()) {
dispatch.maybeSetLogger(logger);
}
}
}
}
--------------------------------------------------------------------------------
public <T> T getBroadcaster(Class<T> listenerClass) { //interface 3
return getBroadcasterInternal(listenerClass).getSource();
}
private <T> ListenerBroadcast<T> getBroadcasterInternal(Class<T> listenerClass) {
synchronized (lock) {
ListenerBroadcast<T> broadcaster = broadcasters.get(listenerClass);
if (broadcaster == null) {
broadcaster = new ListenerBroadcast<T>(listenerClass);
//Add dispatch object into broadcaster's handlers queue.
broadcaster.add(getLogger(listenerClass));
broadcaster.add(getDispatcher(listenerClass));
if (parent != null) {
broadcaster.add(parent.getDispatcher(listenerClass));
}
broadcasters.put(listenerClass, broadcaster);
}
return broadcaster;
}
}
private LoggerDispatch getLogger(Class<?> listenerClass) {
synchronized (lock) {
LoggerDispatch dispatch = loggers.get(listenerClass);
if (dispatch == null) {
dispatch = new LoggerDispatch(listenerClass, parent == null ? null : parent.getLogger(listenerClass));
<span style="white-space:pre"> </span>//when called by parent, the dispatch.dispath is null, but the 'allLoggers' is not, so it try to assign a value to dispath.dispatch by calling maybeSetLogger function
for (Object logger : allLoggers) {
dispatch.maybeSetLogger(logger);
}
loggers.put(listenerClass, dispatch);
}
return dispatch;
}
}
private LoggerDispatch(Class<?> type, LoggerDispatch parentDispatch) {
this.type = type;
this.dispatch = parentDispatch;
}
//1.In org.gradle.initialization DefaultGradleLauncherFactory.java
//The constructor of DefaultGradleLauncherFactory
// Register default loggers
ListenerManager listenerManager = sharedServices.get(ListenerManager.class);
buildProgressLogger = new BuildProgressLogger(sharedServices.get(ProgressLoggerFactory.class));
//interface 1, 'allListeners' is empty, and only add item to Set<>, do nothing else.
listenerManager.addListener(new BuildProgressFilter(buildProgressLogger));
//interface 2, 'allLoggers' is empty, and only add item to Set<>, do nothing else
listenerManager.useLogger(new DependencyResolutionLogger(sharedServices.get(ProgressLoggerFactory.class)));
//2. Same package, DefaultGradleLauncherFactory.java
//doNewInstance function
//小插曲,調用了一下函數 from BuildScopeServies::createListenerManager
/*
public ListenerManager createChild() {
return new DefaultListenerManager(this);
}
*/
//Then the 'listenerManager' is a totally new object,
//and the one before becomes its 'parent'
ListenerManager listenerManager = serviceRegistry.get(ListenerManager.class);
//this hooks up the ListenerManager and LoggingConfigurer so you can call Gradle.addListener() with a StandardOutputListener.
//Interface 3, 'broadcasters' map is empty , then new an ListenerBroadcast object 'broadcaster'
//In 'getLogger', the 'loggers' is empty,
//in new LoggerDispatch, it will call parent.getLogger first (遞歸), parent's loggers is empty
//so parent listenerManager will return a LoggerDispatch object, with 'dispatch' null, and put it into parent's loggers queue.
//To son's turn, the new LoggerDispatch will be an object with 'dispatch' point to the object returned from parent.
//Parent.loggers.values constains a value of DefaultListenerManager$LoggerDispatch (id=196), its dispatch is null
//this.loggers.values constains value of DefaultListenerManager$LoggerDispatch, it's dispatch var member is also a DefaultListenerManager$LoggerDispatch
//with id=196, so the parent/child chain is made
loggingManager.addStandardOutputListener(listenerManager.getBroadcaster(StandardOutputListener.class));
執行完
listenerManager.getBroadcaster(StandardOutputListener.class)以後,listenerManager 和它的parent的成員結構大致如下, 數字是調試時候的id