 .../apache/solr/core/SolrCoreCloseListener.java    | 42 ++++++++++++++++++++++
 .../src/java/org/apache/solr/core/SolrCores.java   |  9 ++---
 .../apache/solr/core/TransientSolrCoreCache.java   | 27 +++++++++++++-
 .../solr/core/TransientSolrCoreCacheDefault.java   | 14 +++-----
 4 files changed, 76 insertions(+), 16 deletions(-)

diff --git a/solr/core/src/java/org/apache/solr/core/SolrCoreCloseListener.java b/solr/core/src/java/org/apache/solr/core/SolrCoreCloseListener.java
new file mode 100644
index 0000000..4a5b41c
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/core/SolrCoreCloseListener.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.core;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+/**
+ * Notifies observers implementing this class about cores that need to be closed.
+ */
+public interface SolrCoreCloseListener extends PropertyChangeListener {
+
+  /**
+   * Called by TransientSolrCoreCache to notify the CoreContainer / SolrCores about cores that need to be closed.
+   * @param core Core that need to be queued for close
+   */
+  void queueCoreClose(SolrCore core);
+
+  @Override
+  default void propertyChange(PropertyChangeEvent evt) {
+    queueCoreClose((SolrCore) evt.getOldValue());
+  }
+
+}
+
+
+  
diff --git a/solr/core/src/java/org/apache/solr/core/SolrCores.java b/solr/core/src/java/org/apache/solr/core/SolrCores.java
index 73d97da..43034a5 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrCores.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrCores.java
@@ -25,8 +25,6 @@ import org.apache.solr.util.DefaultSolrThreadFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
 import java.lang.invoke.MethodHandles;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -42,7 +40,7 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.TimeUnit;
 
 
-class SolrCores implements PropertyChangeListener {
+class SolrCores implements SolrCoreCloseListener {
 
   private static Object modifyLock = new Object(); // for locking around manipulating any of the core maps.
   private final Map<String, SolrCore> cores = new LinkedHashMap<>(); // For "permanent" cores
@@ -536,10 +534,9 @@ class SolrCores implements PropertyChangeListener {
 
   // Let transient cache implementation tell us when it ages out a core
   @Override
-  public void propertyChange(PropertyChangeEvent evt) {
+  public void queueCoreClose(SolrCore core) {
     synchronized (modifyLock) {
       // Erick Erickson debugging TestLazyCores. With this un-commented, we get no testLazyCores failures.
-//      SolrCore core = (SolrCore) arg;
 //      SolrQueryRequest req = new LocalSolrQueryRequest(core, new ModifiableSolrParams());
 //      CommitUpdateCommand cmd = new CommitUpdateCommand(req, false);
 //      cmd.openSearcher = false;
@@ -549,7 +546,7 @@ class SolrCores implements PropertyChangeListener {
 //      } catch (IOException e) {
 //        log.warn("Caught exception trying to close a transient core, ignoring as it should be benign");
 //      }
-      pendingCloses.add((SolrCore) evt.getOldValue()); // Essentially just queue this core up for closing.
+      pendingCloses.add(core); // Essentially just queue this core up for closing.
       modifyLock.notifyAll(); // Wakes up closer thread too
     }
   }
diff --git a/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCache.java b/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCache.java
index 3f6cc8c..3af7e23 100644
--- a/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCache.java
+++ b/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCache.java
@@ -18,6 +18,7 @@
 package org.apache.solr.core;
 
 
+import java.beans.PropertyChangeSupport;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -44,7 +45,7 @@ import org.apache.http.annotation.Experimental;
  *          necessary and to coordinate shutting down cores, manipulating the internal structures and the like..
  *          
  *          The only real action you should _initiate_ is to close a core for whatever reason, and do that by 
- *          calling notifyObservers(coreToClose); The observer will call back to removeCore(name) at the appropriate 
+ *          calling notifyCoreCloseListener(coreToClose); The observer will call back to removeCore(name) at the appropriate 
  *          time. There is no need to directly remove the core _at that time_ from the transientCores list, a call
  *          will come back to this class when CoreContainer is closing this core.
  *          
@@ -120,6 +121,30 @@ public abstract class TransientSolrCoreCache {
   // These two methods allow custom implementations to communicate arbitrary information as necessary.
   public abstract int getStatus(String coreName);
   public abstract void setStatus(String coreName, int status);
+  
+  
+  /**
+   * Registers a listener to be notified when a core should close
+   */
+  protected final void registerCoreCloseListener(SolrCoreCloseListener listener) {
+    pcs.addPropertyChangeListener(listener);
+  }
+  
+  /**
+   * Removes a listener registered by {@link #registerCoreCloseListener(SolrCoreCloseListener)}
+   */
+  protected final void removeCoreCloseListener(SolrCoreCloseListener listener) {
+    pcs.removePropertyChangeListener(listener);
+  }
+  
+  /**
+   * Notifies all listeners to close a core that were previously registered using {@link #registerCoreCloseListener(SolrCoreCloseListener)}
+   */
+  protected final void notifyCoreCloseListeners(SolrCore core) {
+    pcs.firePropertyChange("core", core, null);
+  }
+  
+  private final PropertyChangeSupport pcs = new  PropertyChangeSupport(this);
 }
 
 
diff --git a/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCacheDefault.java b/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCacheDefault.java
index 5cd3537..0b3db4b 100644
--- a/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCacheDefault.java
+++ b/solr/core/src/java/org/apache/solr/core/TransientSolrCoreCacheDefault.java
@@ -17,8 +17,6 @@
 
 package org.apache.solr.core;
 
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
 import java.lang.invoke.MethodHandles;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -37,7 +35,7 @@ public class TransientSolrCoreCacheDefault extends TransientSolrCoreCache {
 
   private int cacheSize = NodeConfig.NodeConfigBuilder.DEFAULT_TRANSIENT_CACHE_SIZE;
 
-  protected PropertyChangeListener coreChangeListener;
+  protected SolrCoreCloseListener coreCloseListener;
   protected CoreContainer coreContainer;
 
   protected final Map<String, CoreDescriptor> transientDescriptors = new LinkedHashMap<>();
@@ -45,14 +43,12 @@ public class TransientSolrCoreCacheDefault extends TransientSolrCoreCache {
   //WARNING! The _only_ place you put anything into the list of transient cores is with the putTransientCore method!
   protected Map<String, SolrCore> transientCores = new LinkedHashMap<>(); // For "lazily loaded" cores
 
-  private final PropertyChangeSupport pcs = new  PropertyChangeSupport(this);
-
   /**
    * @param container The enclosing CoreContainer. It allows us to access everything we need.
    */
   public TransientSolrCoreCacheDefault(final CoreContainer container) {
     this.coreContainer = container;
-    this.coreChangeListener= coreContainer.solrCores;
+    this.coreCloseListener = coreContainer.solrCores;
     
     NodeConfig cfg = container.getNodeConfig();
     if (cfg.getTransientCachePluginInfo() == null) {
@@ -83,7 +79,7 @@ public class TransientSolrCoreCacheDefault extends TransientSolrCoreCache {
     }
 
     log.info("Allocating transient cache for {} transient cores", cacheSize);
-    pcs.addPropertyChangeListener(this.coreChangeListener);
+    this.registerCoreCloseListener(this.coreCloseListener);
     // it's possible for cache
     if (cacheSize < 0) { // Trap old flag
       cacheSize = Integer.MAX_VALUE;
@@ -95,8 +91,8 @@ public class TransientSolrCoreCacheDefault extends TransientSolrCoreCache {
       protected boolean removeEldestEntry(Map.Entry<String, SolrCore> eldest) {
         if (size() > cacheSize) {
           SolrCore coreToClose = eldest.getValue();
-          pcs.firePropertyChange("core", coreToClose, null);
           log.info("Closing transient core [{}]", coreToClose.getName());
+          notifyCoreCloseListeners(coreToClose);
           return true;
         }
         return false;
@@ -186,7 +182,7 @@ public class TransientSolrCoreCacheDefault extends TransientSolrCoreCache {
    */
   @Override
   public void close() {
-    pcs.removePropertyChangeListener(this.coreChangeListener);
+    this.removeCoreCloseListener(this.coreCloseListener);
   }
 
 
