package net.greencoding.thysdrus.circuitbreaker.springaop;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.greencoding.thysdrus.circuitbreaker.annotation.MonitoredByCircuitBreakerBean;
import net.greencoding.thysdrus.circuitbreaker.core.handler.CircuitBreakerHandler;
import net.greencoding.thysdrus.circuitbreaker.core.handler.DefaultCircuitBreakerHandler;
import net.greencoding.thysdrus.circuitbreaker.core.model.CircuitBreaker;
import org.reflections.Reflections;
import org.reflections.scanners.MethodAnnotationsScanner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
public class CircuitBreakerDiscoverer implements InitializingBean {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
ApplicationContext context;
private CircuitBreakerHandler cbHandler = DefaultCircuitBreakerHandler.getSingleton();
//@Override
public void afterPropertiesSet() throws Exception {
String beanNames [] = context.getBeanNamesForType(CircuitBreakerDefinition.class);
if (beanNames != null && beanNames.length > 0){
Reflections reflections = new Reflections("",new MethodAnnotationsScanner());
Set<Method> methods = reflections.getMethodsAnnotatedWith(MonitoredByCircuitBreakerBean.class);
logger.info("methods: " + methods);
if (methods == null) {
return;
}
// scan the class path for annotation store them in a map <beanId, method>
Map<String, List<Method>> annotatedMethods = new HashMap<String, List<Method>>();
Iterator<Method> iterator = methods.iterator();
while (iterator.hasNext()){
Method method = iterator.next();
MonitoredByCircuitBreakerBean annotation = method.getAnnotation(MonitoredByCircuitBreakerBean.class);
if (annotation != null){
List<Method> methodList = annotatedMethods.get(annotation.value());
if (methodList == null) {
methodList = new ArrayList<Method>();
}
methodList.add(method);
annotatedMethods.put(annotation.value(), methodList);
}
}
for (String beanName : beanNames) {
CircuitBreakerDefinition cbDefinition = (CircuitBreakerDefinition) context.getBean(beanName);
CircuitBreaker circuitBreaker = new CircuitBreaker();
String key = cbDefinition.getCircuitBreakerKey() == null ? beanName : cbDefinition.getCircuitBreakerKey() ;
circuitBreaker.setCircuitBreakerKey(key);
circuitBreaker.setFailureIndications(cbDefinition.getFailureIndications());
circuitBreaker.setFailureThreshold(cbDefinition.getFailureThreshold());
circuitBreaker.setFailureThresholdTimeFrameMs(cbDefinition.getFailureThresholdTimeFrameMs());
circuitBreaker.setRetryTimeoutMs(cbDefinition.getRetryTimeoutMs());
circuitBreaker.setRegisteredMethods(annotatedMethods.get(beanName));
cbHandler.registerCircuitBreaker(circuitBreaker);
}
}
}
}