code: private static void addRecursive(
          Object object, PropertyChangeListener propertyChangeListener,
          Set<Object> processedObjects)
      {
          Objects.requireNonNull(processedObjects, 
              "The processedObjects may not be null");
          if (object == null)
          {
              return;
          }
          if (processedObjects.contains(object))
          {
              return;
          }
          processedObjects.add(object);
          if (object.getClass().isArray())
          {
              int length = Array.getLength(object);
              for (int i = 0; i < length; i++)
              {
                  Object element = Array.get(object, i);
                  addRecursive(element, 
                      propertyChangeListener, processedObjects);
              }
              return;
          }
          PropertyChangeUtils.tryAddPropertyChangeListenerUnchecked(
              object, propertyChangeListener);
          List<String> propertyNames =
              BeanUtils.getMutablePropertyNamesOptional(object.getClass());
          for (String propertyName : propertyNames)
          {
              Object value = 
                  BeanUtils.invokeReadMethodOptional(object, propertyName);
              addRecursive(value, propertyChangeListener, processedObjects);
          }
      }
docs: Recursively add the given property change listener to the given
  object and all its sub-objects
  
  @param object The object
  @param propertyChangeListener The property change listener
  @param processedObjects The set of objects that have already been
  processed.