Hello, while profiling workload that creates lots of projections I've found out that about 33% of ProxyFactory.getProxy() are taken by JdkDynamicAopProxy.findDefinedEqualsAndHashCodeMethods, see attachment: The hot spot is here:

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
    if (logger.isTraceEnabled()) {
        logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
    }
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

It looks like we don't need to call either JdkDynamicAopProxy.findDefinedEqualsAndHashCodeMethods, or AopProxyUtils.completeProxiedInterfaces() at each invocation of JdkDynamicAopProxy.getProxy, because their results don't depend on ClassLoader argument and can be calculated only once at obejct construction time, also advised field is declared final.

Also related methods of ReflectionUtils could also be trivially improved.