@Nullable
    default <T> T unwrap(Object client, Class<T> type) {
        requireNonNull(client, "client");
        requireNonNull(type, "type");

        if (type.isInstance(client)) {
            return type.cast(client);
        }

        if (client instanceof Unwrappable) {
            return ((Unwrappable) client).as(type);
        }

        if (Proxy.isProxyClass(client.getClass())) {
            final InvocationHandler handler = Proxy.getInvocationHandler(client);
            if (type.isInstance(handler)) {
                return type.cast(handler);
            }

            if (handler instanceof Unwrappable) {
                return ((Unwrappable) handler).as(type);
            }
        }

        return null;
    }
Unwraps the specified {@code client} object into the object of the specified {@code type}. For example,
<pre>{@code
ClientFactory clientFactory = ...;
WebClient client = WebClient.builder(...)
                            .factory(clientFactory)
                            .decorator(LoggingClient.newDecorator())
                            .build();

LoggingClient unwrapped = clientFactory.unwrap(client, LoggingClient.class);

// If the client implements Unwrappable, you can just use the 'as()' method.
LoggingClient unwrapped2 = client.as(LoggingClient.class);
}</pre>

@param client the client object
@param type the type of the object to return
@return the object of the specified {@code type} if found, or {@code null} if not found.

@see Client#as(Class)
@see Clients#unwrap(Object, Class)
@see Unwrappable
core/src/main/java/com/linecorp/armeria/client/ClientFactory.java