001package org.javasimon.spring;
002
003import java.io.Serializable;
004
005import org.aopalliance.intercept.MethodInterceptor;
006import org.aopalliance.intercept.MethodInvocation;
007import org.javasimon.Manager;
008import org.javasimon.SimonManager;
009import org.javasimon.Split;
010import org.javasimon.source.StopwatchSource;
011
012/**
013 * Basic method interceptor that measures the duration of the intercepted call with a Stopwatch.
014 * Class can be overridden in case more sophisticated measuring needs to be provided - this all should
015 * happen in {@link #processInvoke(org.aopalliance.intercept.MethodInvocation, org.javasimon.Split)} method.
016 *
017 * @author Erik van Oosten
018 */
019public class BasicMonitoringInterceptor implements MethodInterceptor, Serializable {
020        private final StopwatchSource<MethodInvocation> stopwatchSource;
021
022        /**
023         * Constructor with specified {@link org.javasimon.source.MonitorSource}.
024         *
025         * @param stopwatchSource stopwatch provider for method invocation
026         */
027        public BasicMonitoringInterceptor(StopwatchSource<MethodInvocation> stopwatchSource) {
028                this.stopwatchSource = stopwatchSource;
029        }
030
031        /** Constructor with specified {@link org.javasimon.Manager}. */
032        public BasicMonitoringInterceptor(Manager manager) {
033                this(new SpringStopwatchSource(manager));
034        }
035
036        /** Default constructor using {@link org.javasimon.SimonManager#manager}. */
037        public BasicMonitoringInterceptor() {
038                this(new SpringStopwatchSource(SimonManager.manager()));
039        }
040
041        /**
042         * Performs method invocation and wraps it with Stopwatch.
043         *
044         * @param invocation method invocation
045         * @return return object from the method
046         * @throws Throwable anything thrown by the method
047         */
048        public final Object invoke(MethodInvocation invocation) throws Throwable {
049                final Split split = stopwatchSource.start(invocation);
050                try {
051                        return processInvoke(invocation, split);
052                } finally {
053                        split.stop();
054                }
055        }
056
057        /**
058         * Method with default invoke (just calls proceed). It can be overridden and overriding method can stop
059         * the provided split. If split is not stopped it will be stopped right after this method finishes.
060         * Any caught throwable should be rethrown again. Method should call {@code invocation.proceed()}.
061         *
062         * @param invocation method invocation
063         * @param split running split for this monitored action
064         * @return return object from the method
065         */
066        protected Object processInvoke(MethodInvocation invocation, @SuppressWarnings("UnusedParameters") Split split) throws Throwable {
067                return invocation.proceed();
068        }
069}