org.javasimon.spring.SpringStopwatchSource Maven / Gradle / Ivy
package org.javasimon.spring;
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInvocation;
import org.javasimon.Manager;
import org.javasimon.aop.Monitored;
import org.javasimon.source.AbstractMethodStopwatchSource;
import org.springframework.aop.SpringProxy;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.support.AopUtils;
import org.springframework.core.annotation.AnnotationUtils;
/**
* Monitor source providing stopwatches from Spring AOP method invocation.
*
* @author gquintana
*/
public class SpringStopwatchSource extends AbstractMethodStopwatchSource {
/**
* Constructor with specified {@link Manager}.
*
* @param manager Simon manager used for producing Stopwatches
*/
public SpringStopwatchSource(Manager manager) {
super(manager);
}
/** Get target class. */
protected final Class> getTargetClass(MethodInvocation methodInvocation) {
return AopUtils.getTargetClass(methodInvocation.getThis());
}
/**
* Get method being invoked.
*
* @param methodInvocation Method invocation
* @return Method being invoked
*/
@Override
protected Method getTargetMethod(MethodInvocation methodInvocation) {
return getTargetMethod(methodInvocation, getTargetClass(methodInvocation));
}
private Method getTargetMethod(MethodInvocation methodInvocation, Class> targetClass) {
return AopUtils.getMostSpecificMethod(methodInvocation.getMethod(), targetClass);
}
/**
* By default returns {@code true} because it is expected to be called from {@link MonitoringInterceptor} which means that the method call
* should be monitored. Pointcuts provided enough mechanism to decide whether the method is monitored or not, but this method can be overridden
* if needed.
*
* @param methodInvocation current method invocation
* @return true, if the method invocation should be monitored
*/
@Override
public boolean isMonitored(MethodInvocation methodInvocation) {
return true;
}
/**
* Returns monitor name for the given method invocation with {@link org.javasimon.aop.Monitored#name()}
* and {@link org.javasimon.aop.Monitored#suffix()} applied as expected.
*
* @param methodInvocation current method invocation
* @return name of the Stopwatch for the invocation
*/
protected String getMonitorName(MethodInvocation methodInvocation) {
Class> targetClass = getTargetClass(methodInvocation);
Method targetMethod = getTargetMethod(methodInvocation, targetClass);
Monitored methodAnnotation = AnnotationUtils.findAnnotation(targetMethod, Monitored.class);
if (methodAnnotation != null && methodAnnotation.name() != null && methodAnnotation.name().length() > 0) {
return methodAnnotation.name();
}
StringBuilder nameBuilder = new StringBuilder();
Monitored classAnnotation = AnnotationUtils.findAnnotation(targetClass, Monitored.class);
if (classAnnotation != null && classAnnotation.name() != null && classAnnotation.name().length() > 0) {
nameBuilder.append(classAnnotation.name());
} else {
nameBuilder.append(getMeaningfulClassName(targetClass));
}
nameBuilder.append(Manager.HIERARCHY_DELIMITER);
String suffix = targetMethod.getName();
if (methodAnnotation != null && methodAnnotation.suffix() != null && methodAnnotation.suffix().length() > 0) {
suffix = methodAnnotation.suffix();
}
return nameBuilder.append(suffix).toString();
}
protected String getMeaningfulClassName(Class> targetClass) {
if (java.lang.reflect.Proxy.isProxyClass(targetClass)) {
for (Class> iface : targetClass.getInterfaces()) {
if (iface != SpringProxy.class && iface != Advised.class) {
return iface.getName();
}
}
}
return targetClass.getName();
}
}