Suppress CGLIB validation WARN for lifecycle callbacks - #36935
Suppress CGLIB validation WARN for lifecycle callbacks#36935seonwooj0810 wants to merge 1 commit into
Conversation
When CglibAopProxy validates the target class it logs a WARN for each public final method that implements an interface, suggesting to use interface-based JDK proxies instead. For final methods inherited from Spring's configuration callback interfaces (InitializingBean, DisposableBean, Aware sub-interfaces, Closeable, AutoCloseable) that recommendation is misleading: those methods are container-driven, are not advised by typical application pointcuts, and the user usually cannot make them non-final. The validation now only emits the WARN when at least one user-defined interface declares the method. Methods inherited exclusively from configuration callback interfaces fall back to the existing DEBUG diagnostic. Closes spring-projectsgh-35365 Signed-off-by: seonwoo_jung <laborlawseon@kap.kr>
|
Gentle ping — open since mid-June.
Is an explicit allowlist acceptable here, or would you prefer a broader rule? Still merges cleanly, checks green. |
|
Thanks for the PR and the gentle ping @seonwooj0810. 👍 We'll look into this. |
sbrannen
left a comment
There was a problem hiding this comment.
I've requested a change regarding the duplicated utility method.
| * {@link Closeable}/{@link AutoCloseable}, or an {@link Aware} sub-interface). | ||
| * <p>Mirrors {@code ProxyProcessorSupport#isConfigurationCallbackInterface}. | ||
| */ | ||
| private static boolean isConfigurationCallbackInterface(Class<?> ifc) { |
There was a problem hiding this comment.
Instead of duplicating this here, please extract the existing isConfigurationCallbackInterface(Class) method into a package-private method with the same signature in AopProxyUtils, have the existing isConfigurationCallbackInterface(Class) method in ProxyProcessorSupport and this class delegate to the new method, and delete this duplicate copy.
Closes gh-35365
What's going on
CglibAopProxy.doValidateClasswalks every method of the proxy super class and, for eachpublic finalmethod that overrides an interface, logs at WARN:For methods that come from Spring's configuration callback interfaces (
InitializingBean,DisposableBean,Awaresub-interfaces,Closeable,AutoCloseable) that recommendation is misleading on multiple levels:finalprecisely because the framework (or a base class likeWebServiceGatewaySupport) wants to guarantee the lifecycle step runs.@Timed,@Transactional) which means CGLIB is the only viable proxy mechanism anyway.afterPropertiesSet()/destroy()/set*Aware(...)itself, so the missed advice the warning hints at doesn't actually exist.The result is alarming noise during startup for users who run
WebServiceGatewaySupport,JmsGatewaySupport, or any of the other framework base classes with afinal afterPropertiesSet()together with a class-level AOP annotation. The reproducer in the linked issue (a bare-bones class withfinal afterPropertiesSet()+@Timed) triggers the WARN.The change
doValidateClassnow uses a small helper,implementsOnlyConfigurationCallbackInterfaces, that returnstruewhen every interface declaring the method is one of the configuration callback interfaces enumerated inProxyProcessorSupport#isConfigurationCallbackInterface. The WARN about aninterface-implementingfinal method is skipped in that case, and the existing DEBUG-level diagnostic indoValidateClass(which already explains the consequence in detail) is retained for users who want the information.Two cases continue to log the WARN unchanged:
The helper deliberately mirrors
ProxyProcessorSupport#isConfigurationCallbackInterfacerather than reaching across to call it, so the public API ofProxyProcessorSupportdoesn't change and the two classes stay independent.Verification
CglibAopProxyConfigurationCallbackTestswith seven cases coveringInitializingBean,DisposableBean,BeanFactoryAware,Closeable, a user-only interface, a method shared between a callback and a user interface, and a standalone final method without any matching interface../gradlew :spring-aop:test(full module) - green../gradlew :spring-context:test --tests "*Proxy*Tests" --tests "org.springframework.aop.*"- green, exercising the CGLIB validation path through the broader proxying machinery.Verification done: (1) confirmed no in-flight PR via
gh pr list --search "35365 OR final afterPropertiesSet OR doValidateClass"and the linked-PR query on the issue, (2) no claim comments on the issue thread, (3) fix touches.javaonly (CglibAopProxy.java+ a new test), (4) grepped main for theUnable to proxy interface-implementing methodstring - still present inCglibAopProxy.java:295, (6) maintainer @snicoll transferred the issue to spring-framework with "I wonder if Spring Framework could do something about this" and replicated the noise on a bare-bones project, which is the engagement signal I targeted.