com.developmentsprint.spring.breaker.annotations.AnnotationCircuitBreakerAttributeSource.java Source code

Java tutorial

Introduction

Here is the source code for com.developmentsprint.spring.breaker.annotations.AnnotationCircuitBreakerAttributeSource.java

Source

/**
 * 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();
    }

}