Skip to content

Commit

Permalink
Support for meta-annotations ryantenney#163
Browse files Browse the repository at this point in the history
  • Loading branch information
aheil committed Jan 25, 2016
1 parent 19ff366 commit 7b1308b
Show file tree
Hide file tree
Showing 9 changed files with 302 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.aopalliance.intercept.MethodInvocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.MethodCallback;
import org.springframework.util.ReflectionUtils.MethodFilter;
Expand Down Expand Up @@ -65,7 +66,7 @@ public Object invoke(MethodInvocation invocation) throws Throwable {

@Override
public void doWith(Method method) throws IllegalAccessException {
final A annotation = method.getAnnotation(annotationClass);
final A annotation = AnnotationUtils.findAnnotation(method, annotationClass);
if (annotation != null) {
final MethodKey methodKey = MethodKey.forMethod(method);
final String metricName = buildMetricName(targetClass, method, annotation);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/**
* Copyright (C) 2012 Ryan W Tenney ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.ryantenney.metrics.spring;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.concurrent.atomic.AtomicBoolean;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
import org.springframework.aop.support.annotation.AnnotationClassFilter;
import org.springframework.aop.support.annotation.AnnotationMethodMatcher;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ReflectionUtils;

/**
Based on spring retry (org.springframework.retry.annotation.RetryConfiguration).
*/
public class AnnotationClassOrMethodPointcut extends StaticMethodMatcherPointcut {

private final MethodMatcher methodResolver;

AnnotationClassOrMethodPointcut(Class<? extends Annotation> annotationType) {
this.methodResolver = new AnnotationMethodMatcher(annotationType);
setClassFilter(new AnnotationClassOrMethodFilter(annotationType));
}

@Override
public boolean matches(Method method, Class<?> targetClass) {
return getClassFilter().matches(targetClass) || this.methodResolver.matches(method, targetClass);
}

private static final class AnnotationClassOrMethodFilter extends AnnotationClassFilter {

private final AnnotationMethodsResolver methodResolver;

AnnotationClassOrMethodFilter(Class<? extends Annotation> annotationType) {
super(annotationType, true);
this.methodResolver = new AnnotationMethodsResolver(annotationType);
}

@Override
public boolean matches(Class<?> clazz) {
return super.matches(clazz) || this.methodResolver.hasAnnotatedMethods(clazz);
}

@Override
public boolean equals(Object other) {

return super.equals(other);
}

@Override
public int hashCode() {

return super.hashCode();
}
}

private static class AnnotationMethodsResolver {

private Class<? extends Annotation> annotationType;

public AnnotationMethodsResolver(Class<? extends Annotation> annotationType) {
this.annotationType = annotationType;
}

public boolean hasAnnotatedMethods(Class<?> clazz) {
final AtomicBoolean found = new AtomicBoolean(false);
ReflectionUtils.doWithMethods(clazz,
new ReflectionUtils.MethodCallback() {
@Override
public void doWith(Method method) throws IllegalArgumentException,
IllegalAccessException {
if (found.get()) {
return;
}
Annotation annotation = AnnotationUtils.findAnnotation(method,
annotationType);
if (annotation != null) { found.set(true); }
}
});
return found.get();
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ReflectionUtils.FieldFilter;
import org.springframework.util.ReflectionUtils.MethodFilter;

Expand Down Expand Up @@ -69,7 +70,7 @@ public AnnotationFilter(final Class<? extends Annotation> clazz, final int metho

@Override
public boolean matches(Method method) {
if (USER_DECLARED_METHODS.matches(method) && method.isAnnotationPresent(clazz)) {
if (USER_DECLARED_METHODS.matches(method) && AnnotationUtils.findAnnotation(method, clazz) != null) {
if (checkModifiers(method, methodModifiers)) {
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,21 @@
*/
package com.ryantenney.metrics.spring;

import com.codahale.metrics.Counter;
import com.codahale.metrics.MetricRegistry;
import com.ryantenney.metrics.annotation.Counted;
import java.lang.reflect.Method;

import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
import org.springframework.util.ReflectionUtils.MethodFilter;

import com.codahale.metrics.Counter;
import com.codahale.metrics.MetricRegistry;
import com.ryantenney.metrics.annotation.Counted;

import static com.ryantenney.metrics.spring.AnnotationFilter.PROXYABLE_METHODS;

class CountedMethodInterceptor extends AbstractMetricMethodInterceptor<Counted, Counter> {

public static final Class<Counted> ANNOTATION = Counted.class;
public static final Pointcut POINTCUT = new AnnotationMatchingPointcut(null, ANNOTATION);
public static final Pointcut POINTCUT = new AnnotationClassOrMethodPointcut(ANNOTATION);
public static final MethodFilter METHOD_FILTER = new AnnotationFilter(ANNOTATION, PROXYABLE_METHODS);

public CountedMethodInterceptor(final MetricRegistry metricRegistry, final Class<?> targetClass) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,22 @@
*/
package com.ryantenney.metrics.spring;

import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.annotation.ExceptionMetered;
import java.lang.reflect.Method;

import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
import org.springframework.core.Ordered;
import org.springframework.util.ReflectionUtils.MethodFilter;

import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.annotation.ExceptionMetered;

import static com.ryantenney.metrics.spring.AnnotationFilter.PROXYABLE_METHODS;

class ExceptionMeteredMethodInterceptor extends AbstractMetricMethodInterceptor<ExceptionMetered, Meter> implements Ordered {

public static final Class<ExceptionMetered> ANNOTATION = ExceptionMetered.class;
public static final Pointcut POINTCUT = new AnnotationMatchingPointcut(null, ANNOTATION);
public static final Pointcut POINTCUT = new AnnotationClassOrMethodPointcut(ANNOTATION);
public static final MethodFilter METHOD_FILTER = new AnnotationFilter(ANNOTATION, PROXYABLE_METHODS);

public ExceptionMeteredMethodInterceptor(final MetricRegistry metricRegistry, final Class<?> targetClass) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,21 @@
*/
package com.ryantenney.metrics.spring;

import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.annotation.Metered;
import java.lang.reflect.Method;

import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
import org.springframework.util.ReflectionUtils.MethodFilter;

import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.annotation.Metered;

import static com.ryantenney.metrics.spring.AnnotationFilter.PROXYABLE_METHODS;

class MeteredMethodInterceptor extends AbstractMetricMethodInterceptor<Metered, Meter> {

public static final Class<Metered> ANNOTATION = Metered.class;
public static final Pointcut POINTCUT = new AnnotationMatchingPointcut(null, ANNOTATION);
public static final Pointcut POINTCUT = new AnnotationClassOrMethodPointcut(ANNOTATION);
public static final MethodFilter METHOD_FILTER = new AnnotationFilter(ANNOTATION, PROXYABLE_METHODS);

public MeteredMethodInterceptor(final MetricRegistry metricRegistry, final Class<?> targetClass) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,23 @@
*/
package com.ryantenney.metrics.spring;

import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
import com.codahale.metrics.Timer.Context;
import com.codahale.metrics.annotation.Timed;
import java.lang.reflect.Method;

import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
import org.springframework.core.Ordered;
import org.springframework.util.ReflectionUtils.MethodFilter;

import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
import com.codahale.metrics.Timer.Context;
import com.codahale.metrics.annotation.Timed;

import static com.ryantenney.metrics.spring.AnnotationFilter.PROXYABLE_METHODS;

class TimedMethodInterceptor extends AbstractMetricMethodInterceptor<Timed, Timer> implements Ordered {

public static final Class<Timed> ANNOTATION = Timed.class;
public static final Pointcut POINTCUT = new AnnotationMatchingPointcut(null, ANNOTATION);
public static final Pointcut POINTCUT = new AnnotationClassOrMethodPointcut(ANNOTATION);
public static final MethodFilter METHOD_FILTER = new AnnotationFilter(ANNOTATION, PROXYABLE_METHODS);

public TimedMethodInterceptor(final MetricRegistry metricRegistry, final Class<?> targetClass) {
Expand Down
Loading

0 comments on commit 7b1308b

Please sign in to comment.