@Override
        @Nullable
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            switch (method.getName()) {
                case "equals":
                    Object other = args[0];
                    // Unwrap proxies for speed
                    if (other instanceof Type) {
                        other = unwrap((Type) other);
                    }
                    return ObjectUtils.nullSafeEquals(this.provider.getType(), other);
                case "hashCode":
                    return ObjectUtils.nullSafeHashCode(this.provider.getType());
                case "getTypeProvider":
                    return this.provider;
                default:
            }

            if (Type.class == method.getReturnType() && ObjectUtils.isEmpty(args)) {
                return forTypeProvider(new MethodInvokeTypeProvider(this.provider, method, -1));
            } else if (Type[].class == method.getReturnType() && ObjectUtils.isEmpty(args)) {
                Type[] result = new Type[((Type[]) method.invoke(this.provider.getType())).length];
                for (int i = 0; i < result.length; i++) {
                    result[i] = forTypeProvider(new MethodInvokeTypeProvider(this.provider, method, i));
                }
                return result;
            }

            try {
                return method.invoke(this.provider.getType(), args);
            } catch (InvocationTargetException ex) {
                throw ex.getTargetException();
            }
        }
{link Serializable} {link InvocationHandler} used by the proxied {link Type}.
Provides serialization support and enhances any methods that return {@code Type}
or {@code Type[]}.
analyzer/src/main/java/nl/basjes/parse/useragent/utils/springframework/core/SerializableTypeWrapper.java