@Override
 public void close() {
   if (cacheMode == CacheMode.CONNECTION) {
     synchronized (connectionMonitor) {
       if (!this.target.isOpen() || idleConnections.size() >= connectionCacheSize) {
         if (logger.isDebugEnabled()) {
           logger.debug("Completely closing connection '" + this + "'");
         }
         if (this.target.isOpen()) {
           RabbitUtils.closeConnection(this.target);
         }
         this.notifyCloseIfNecessary();
         openConnections.remove(this);
         openConnectionNonTransactionalChannels.remove(this);
         openConnectionTransactionalChannels.remove(this);
       } else {
         if (!idleConnections.contains(this)) {
           if (logger.isDebugEnabled()) {
             logger.debug("Returning connection '" + this + "' to cache");
           }
           idleConnections.add(this);
         }
       }
     }
   }
 }
 @Override
 public void log(Log logger, String message, Throwable t) {
   if (t instanceof ShutdownSignalException) {
     ShutdownSignalException cause = (ShutdownSignalException) t;
     if (RabbitUtils.isPassiveDeclarationChannelClose(cause)) {
       if (logger.isDebugEnabled()) {
         logger.debug(message + ": " + cause.getMessage());
       }
     } else if (RabbitUtils.isExclusiveUseChannelClose(cause)) {
       if (logger.isInfoEnabled()) {
         logger.info(message + ": " + cause.getMessage());
       }
     } else if (!RabbitUtils.isNormalChannelClose(cause)) {
       logger.error(message + ": " + cause.getMessage());
     }
   } else {
     logger.error(
         "Unexpected invocation of " + this.getClass() + ", with message: " + message, t);
   }
 }
 public void destroy() {
   if (CachingConnectionFactory.this.cacheMode == CacheMode.CHANNEL) {
     reset(cachedChannelsNonTransactional, cachedChannelsTransactional);
   } else {
     reset(
         openConnectionNonTransactionalChannels.get(this),
         openConnectionTransactionalChannels.get(this));
   }
   if (this.target != null) {
     RabbitUtils.closeConnection(this.target);
     this.notifyCloseIfNecessary();
   }
   this.target = null;
 }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      String methodName = method.getName();
      if (methodName.equals("txSelect") && !this.transactional) {
        throw new UnsupportedOperationException(
            "Cannot start transaction on non-transactional channel");
      }
      if (methodName.equals("equals")) {
        // Only consider equal when proxies are identical.
        return (proxy == args[0]);
      } else if (methodName.equals("hashCode")) {
        // Use hashCode of Channel proxy.
        return System.identityHashCode(proxy);
      } else if (methodName.equals("toString")) {
        return "Cached Rabbit Channel: " + this.target;
      } else if (methodName.equals("close")) {
        // Handle close method: don't pass the call on.
        if (active) {
          synchronized (this.channelList) {
            if (!RabbitUtils.isPhysicalCloseRequired()
                && (this.channelList.size() < getChannelCacheSize()
                    || this.channelList.contains(proxy))) {
              logicalClose((ChannelProxy) proxy);
              // Remain open in the channel list.
              releasePermit();
              return null;
            }
          }
        }

        // If we get here, we're supposed to shut down.
        physicalClose();
        releasePermit();
        return null;
      } else if (methodName.equals("getTargetChannel")) {
        // Handle getTargetChannel method: return underlying Channel.
        return this.target;
      } else if (methodName.equals("isOpen")) {
        // Handle isOpen method: we are closed if the target is closed
        return this.target != null && this.target.isOpen();
      } else if (methodName.equals("isTransactional")) {
        return this.transactional;
      }
      try {
        if (this.target == null || !this.target.isOpen()) {
          if (this.target instanceof PublisherCallbackChannel) {
            this.target.close();
            throw new InvocationTargetException(
                new AmqpException("PublisherCallbackChannel is closed"));
          }
          this.target = null;
        }
        synchronized (targetMonitor) {
          if (this.target == null) {
            this.target = createBareChannel(theConnection, transactional);
          }
          return method.invoke(this.target, args);
        }
      } catch (InvocationTargetException ex) {
        if (this.target == null || !this.target.isOpen()) {
          // Basic re-connection logic...
          if (logger.isDebugEnabled()) {
            logger.debug("Detected closed channel on exception.  Re-initializing: " + this.target);
          }
          this.target = null;
          synchronized (targetMonitor) {
            if (this.target == null) {
              this.target = createBareChannel(theConnection, transactional);
            }
          }
        }
        throw ex.getTargetException();
      }
    }