diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java b/spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java index dceed756b414..d62e12dbe8bc 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java @@ -20,6 +20,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.UndeclaredThrowableException; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; @@ -335,36 +336,39 @@ private Callback[] getCallbacks(Class rootClass) throws Exception { new HashCodeInterceptor(this.advised) }; - Callback[] callbacks; - // If the target is a static one and the advice chain is frozen, // then we can make some optimizations by sending the AOP calls // direct to the target using the fixed chain for that method. if (isStatic && isFrozen) { Method[] methods = rootClass.getMethods(); - Callback[] fixedCallbacks = new Callback[methods.length]; - this.fixedInterceptorMap = CollectionUtils.newHashMap(methods.length); + int methodsCount = methods.length; + List fixedCallbacks = new ArrayList<>(methodsCount); + this.fixedInterceptorMap = CollectionUtils.newHashMap(methodsCount); - // TODO: small memory optimization here (can skip creation for methods with no advice) - for (int x = 0; x < methods.length; x++) { + int advicedMethodCount = methodsCount; + for (int x = 0; x < methodsCount; x++) { Method method = methods[x]; + //do not create advices for non-overridden methods of java.lang.Object + if (method.getDeclaringClass() == Object.class) { + advicedMethodCount--; + continue; + } List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass); - fixedCallbacks[x] = new FixedChainStaticTargetInterceptor( - chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass()); - this.fixedInterceptorMap.put(method, x); + fixedCallbacks.add(new FixedChainStaticTargetInterceptor( + chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass())); + this.fixedInterceptorMap.put(method, x - (methodsCount - advicedMethodCount) ); } // Now copy both the callbacks from mainCallbacks // and fixedCallbacks into the callbacks array. - callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length]; + Callback[] callbacks = new Callback[mainCallbacks.length + advicedMethodCount]; System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length); - System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length); + System.arraycopy(fixedCallbacks.toArray(Callback[]::new), 0, callbacks, + mainCallbacks.length, advicedMethodCount); this.fixedInterceptorOffset = mainCallbacks.length; + return callbacks; } - else { - callbacks = mainCallbacks; - } - return callbacks; + return mainCallbacks; }