Spring cloud Hystrix注解初始化源码过程解读
作者:福
从@EnableCircuitBreaker入手
我们是通过在启动类添加@EnableCircuitBreaker注解启用Hystrix的,所以,源码解析也要从这个注解入手。
该注解已经被标了@Deprecated了,不过,挡不住......
Spring关于@Enablexxxx注解的套路:通过@Import注解引入了EnableCircuitBreakerImportSelector.class:
@Deprecated @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(EnableCircuitBreakerImportSelector.class) public @interface EnableCircuitBreaker { }
跟踪EnableCircuitBreakerImportSelector,继承自SpringFactoryImportSelector<EnableCircuitBreaker>,注意SpringFactoryImportSelector类的泛型类型为EnableCircuitBreaker:
@Order(Ordered.LOWEST_PRECEDENCE - 100) public class EnableCircuitBreakerImportSelector extends SpringFactoryImportSelector<EnableCircuitBreaker> { @Override protected boolean isEnabled() { return getEnvironment().getProperty("spring.cloud.circuit.breaker.enabled", Boolean.class, Boolean.TRUE); } }
看一下类图:
属性annotationClass通过GenericTypeResolver.resolveTypeArgument方法获取当前对象的泛型参数的具体类型,现在我们知道是EnableCircuitBreaker(在org.springframework.cloud.client.circuitbreaker包下)。
public abstract class SpringFactoryImportSelector<T> implements DeferredImportSelector, BeanClassLoaderAware, EnvironmentAware { private final Log log = LogFactory.getLog(SpringFactoryImportSelector.class); private ClassLoader beanClassLoader; private Class<T> annotationClass; private Environment environment; @SuppressWarnings("unchecked") protected SpringFactoryImportSelector() { this.annotationClass = (Class<T>) GenericTypeResolver.resolveTypeArgument(this.getClass(), SpringFactoryImportSelector.class); }
@Import注解我们前面做过详细分析了,实现了DeferredImportSelector接口表示延迟加载全限定名称为selectImports方法返回的类。看selectImports方法:
@Override public String[] selectImports(AnnotationMetadata metadata) { //Enable参数没有打开的话就不加载 if (!isEnabled()) { return new String[0]; } AnnotationAttributes attributes = AnnotationAttributes .fromMap(metadata.getAnnotationAttributes(this.annotationClass.getName(), true)); Assert.notNull(attributes, "No " + getSimpleName() + " attributes found. Is " + metadata.getClassName() + " annotated with @" + getSimpleName() + "?"); // Find all possible auto configuration classes, filtering duplicates //SPI机制调用spring.factories文件下的EnableCircuitBreaker List<String> factories = new ArrayList<>(new LinkedHashSet<>( SpringFactoriesLoader.loadFactoryNames(this.annotationClass, this.beanClassLoader))); if (factories.isEmpty() && !hasDefaultFactory()) { throw new IllegalStateException("Annotation @" + getSimpleName() + " found, but there are no implementations. Did you forget to include a starter?"); } if (factories.size() > 1) { // there should only ever be one DiscoveryClient, but there might be more than // one factory this.log.warn("More than one implementation " + "of @" + getSimpleName() + " (now relying on @Conditionals to pick one): " + factories); } return factories.toArray(new String[factories.size()]); }
selectImports方法的主要功能就是调用SpringFactoriesLoader.loadFactoryNames方法,该方法的目的是通过SPI机制读取spring.factories文件中的org.springframework.cloud.client.circuitbreaker相关配置,返回。
返回的信息是类全限定名,从selectImports方法作用可知,这些类会加载到Spring Ioc容器中。
org.springframework.cloud.client.circuitbreaker在spring-cloud-netflix-hystrix-2.2.10.RELEASE包下:
所以该配置下的org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration会被调用并加载到Spring IoC容器中。
HystrixCircuitBreakerConfiguration
跟踪配置类HystrixCircuitBreakerConfiguration:
/** * @author Spencer Gibb * @author Christian Dupuis * @author Venil Noronha */ @Configuration(proxyBeanMethods = false) public class HystrixCircuitBreakerConfiguration { @Bean public HystrixCommandAspect hystrixCommandAspect() { return new HystrixCommandAspect(); } @Bean public HystrixShutdownHook hystrixShutdownHook() { return new HystrixShutdownHook(); }
注入了一个叫HystrixCommandAspect 的bean,从名字上看,应该是关于HystrixCommand的切面,用到了AOP。其实也容易理解,加了@HystrixCommand注解的方法的执行逻辑发生了变化:方法增强了执行时长是否超时、执行是否成功(是否返回异常)、超时或异常的情况下调用fallback......方法功能的增强正是AOP的强项。
继续跟踪HystrixCommandAspect 类。
HystrixCommandAspect
打开代码,首先是非常熟悉的@Aspect注解:
@Aspect public class HystrixCommandAspect {
表明当前类是AOP的切面。
继续看代码:
@Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand)") public void hystrixCommandAnnotationPointcut() { } @Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser)") public void hystrixCollapserAnnotationPointcut() { } @Around("hystrixCommandAnnotationPointcut() || hystrixCollapserAnnotationPointcut()") public Object methodsAnnotatedWithHystrixCommand(final ProceedingJoinPoint joinPoint) throws Throwable {
添加了针对注解HystrixCommand的切点,以及针对该切点的环绕增强方法methodsAnnotatedWithHystrixCommand。
最终的熔断、限流、服务降级功能,都是在这个methodsAnnotatedWithHystrixCommand方法里实现的,继续向下研究这个方法的代码逻辑,需要RxJava背景知识做支撑。
以上就是Spring cloud Hystrix注解初始化源码过程解读的详细内容,更多关于Spring cloud Hystrix注解初始化的资料请关注脚本之家其它相关文章!