private synchronized <T> Property<T> getOrCreateProperty(final IClientConfigKey<T> key, final Supplier<Optional<T>> valueSupplier, final Supplier<T> defaultSupplier) {
        Preconditions.checkNotNull(valueSupplier, "defaultValueSupplier cannot be null");

        return (Property<T>)dynamicProperties.computeIfAbsent(key, ignore -> new ReloadableProperty<T>() {
                private volatile Optional<T> current = Optional.empty();
                private List<Consumer<T>> consumers = new CopyOnWriteArrayList<>();

                {
                    reload();
                }

                @Override
                public void onChange(Consumer<T> consumer) {
                    consumers.add(consumer);
                }

                @Override
                public Optional<T> get() {
                    return current;
                }

                @Override
                public T getOrDefault() {
                    return current.orElse(defaultSupplier.get());
                }

                @Override
                public void reload() {
                    refreshCounter.incrementAndGet();

                    Optional<T> next = valueSupplier.get();
                    if (!next.equals(current)) {
                        current = next;
                        consumers.forEach(consumer -> consumer.accept(next.orElseGet(defaultSupplier::get)));
                    }
                }

                @Override
                public String toString() {
                    return String.valueOf(get());
                }
            });
    }
Register an action that will refresh the cached value for key. Uses the current value as a reference and will
update from the dynamic property source to either delete or set a new value.

@param key - Property key without client name or namespace
ribbon-core/src/main/java/com/netflix/client/config/ReloadableClientConfig.java