Java tutorial
/** * Copyright 2014 Development Sprint, LLC. * * 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.developmentsprint.spring.breaker.annotations; import java.io.Serializable; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; import org.springframework.util.Assert; import com.developmentsprint.spring.breaker.interceptor.CircuitBreakerAttribute; public class AnnotationCircuitBreakerAttributeSource extends AbstractFallbackCircuitBreakerAttributeSource implements Serializable { private static final long serialVersionUID = 1L; private final boolean publicMethodsOnly; private final Set<CircuitBreakerAnnotationParser> annotationParsers; /** * Create a default AnnotationCircuitBreakerAttributeSource, supporting public methods that carry the {@code CircuitBreaker}. */ public AnnotationCircuitBreakerAttributeSource() { this(true); } /** * Create a custom AnnotationCircuitBreakerAttributeSource, supporting public methods that carry the {@code CircuitBreaker} annotation. * * @param publicMethodsOnly * whether to support public methods that carry the {@code CircuitBreaker} annotation only (typically for use with proxy-based AOP), or * protected/private methods as well (typically used with AspectJ class weaving) */ public AnnotationCircuitBreakerAttributeSource(boolean publicMethodsOnly) { this.publicMethodsOnly = publicMethodsOnly; this.annotationParsers = new LinkedHashSet<CircuitBreakerAnnotationParser>(2); this.annotationParsers.add(new SpringCircuitBreakerAnnotationParser()); } /** * Create a custom AnnotationCircuitBreakerAttributeSource. * * @param annotationParser * the CircuitBreakerAnnotationParser to use */ public AnnotationCircuitBreakerAttributeSource(CircuitBreakerAnnotationParser annotationParser) { this.publicMethodsOnly = true; Assert.notNull(annotationParser, "CircuitBreakerAnnotationParser must not be null"); this.annotationParsers = Collections.singleton(annotationParser); } /** * Create a custom AnnotationTransactionAttributeSource. * * @param annotationParsers * the TransactionAnnotationParsers to use */ public AnnotationCircuitBreakerAttributeSource(CircuitBreakerAnnotationParser... annotationParsers) { this.publicMethodsOnly = true; Assert.notEmpty(annotationParsers, "At least one CircuitBreakerAnnotationParser needs to be specified"); Set<CircuitBreakerAnnotationParser> parsers = new LinkedHashSet<CircuitBreakerAnnotationParser>( annotationParsers.length); Collections.addAll(parsers, annotationParsers); this.annotationParsers = parsers; } /** * Create a custom AnnotationCircuitBreakerAttributeSource. * * @param annotationParsers * the CircuitBreakerAnnotationParsers to use */ public AnnotationCircuitBreakerAttributeSource(Set<CircuitBreakerAnnotationParser> annotationParsers) { this.publicMethodsOnly = true; Assert.notEmpty(annotationParsers, "At least one CircuitBreakerAnnotationParser needs to be specified"); this.annotationParsers = annotationParsers; } @Override protected CircuitBreakerAttribute findCircuitBreakerAttribute(Method method) { return determineCircuitBreakerAttribute(method); } @Override protected CircuitBreakerAttribute findCircuitBreakerAttribute(Class<?> clazz) { return determineCircuitBreakerAttribute(clazz); } /** * Determine the circuit breaker attribute for the given method or class. * <p> * This implementation delegates to configured {@link CircuitBreakerAnnotationParser CircuitBreakerAnnotationParsers} for parsing known annotations into * Spring's metadata attribute class. Returns {@code null} if it's not wired for circuit breaking. * <p> * Can be overridden to support custom annotations that carry transaction metadata. * * @param ae * the annotated method or class * @return CircuitBreakerAttribute the configured circuit breaker attribute, or {@code null} if none was found */ protected CircuitBreakerAttribute determineCircuitBreakerAttribute(AnnotatedElement ae) { for (CircuitBreakerAnnotationParser annotationParser : this.annotationParsers) { CircuitBreakerAttribute attr = annotationParser.parseCircuitBreakerAnnotation(ae); if (attr != null) { return attr; } } return null; } /** * By default, only public methods can be wrapped in a circuit breaker. */ @Override protected boolean allowPublicMethodsOnly() { return this.publicMethodsOnly; } @Override public boolean equals(Object other) { if (this == other) { return true; } if (!(other instanceof AnnotationCircuitBreakerAttributeSource)) { return false; } AnnotationCircuitBreakerAttributeSource otherTas = (AnnotationCircuitBreakerAttributeSource) other; return (this.annotationParsers.equals(otherTas.annotationParsers) && this.publicMethodsOnly == otherTas.publicMethodsOnly); } @Override public int hashCode() { return this.annotationParsers.hashCode(); } }