Browse Source

Explicitly detect (and log) private @Scheduled methods on CGLIB proxies

Issue: SPR-12308
(cherry picked from commit 47ed4d6)
pull/689/head
Juergen Hoeller 12 years ago
parent
commit
473d97350e
  1. 25
      spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java

25
spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java

@ -17,6 +17,7 @@
package org.springframework.scheduling.annotation; package org.springframework.scheduling.annotation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Map; import java.util.Map;
@ -24,6 +25,8 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.support.AopUtils; import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor;
@ -188,17 +191,27 @@ public class ScheduledAnnotationBeanPostProcessor
} }
catch (NoSuchMethodException ex) { catch (NoSuchMethodException ex) {
throw new IllegalStateException(String.format( throw new IllegalStateException(String.format(
"@Scheduled method '%s' found on bean target class '%s', " + "@Scheduled method '%s' found on bean target class '%s' but not " +
"but not found in any interface(s) for bean JDK proxy. Either " + "found in any interface(s) for a dynamic proxy. Either pull the " +
"pull the method up to an interface or switch to subclass (CGLIB) " + "method up to a declared interface or switch to subclass (CGLIB) " +
"proxies by setting proxy-target-class/proxyTargetClass " + "proxies by setting proxy-target-class/proxyTargetClass to 'true'",
"attribute to 'true'", method.getName(), method.getDeclaringClass().getSimpleName())); method.getName(), method.getDeclaringClass().getSimpleName()));
}
}
else if (AopUtils.isCglibProxy(bean)) {
// Common problem: private methods end up in the proxy instance, not getting delegated.
if (Modifier.isPrivate(method.getModifiers())) {
LogFactory.getLog(ScheduledAnnotationBeanPostProcessor.class).warn(String.format(
"@Scheduled method '%s' found on CGLIB proxy for target class '%s' but cannot " +
"be delegated to target bean. Switch its visibility to package or protected.",
method.getName(), method.getDeclaringClass().getSimpleName()));
} }
} }
Runnable runnable = new ScheduledMethodRunnable(bean, method); Runnable runnable = new ScheduledMethodRunnable(bean, method);
boolean processedSchedule = false; boolean processedSchedule = false;
String errorMessage = "Exactly one of the 'cron', 'fixedDelay(String)', or 'fixedRate(String)' attributes is required"; String errorMessage =
"Exactly one of the 'cron', 'fixedDelay(String)', or 'fixedRate(String)' attributes is required";
// Determine initial delay // Determine initial delay
long initialDelay = scheduled.initialDelay(); long initialDelay = scheduled.initialDelay();

Loading…
Cancel
Save