Spring?cloud?Hystrix注解初始化源碼過(guò)程解讀
從@EnableCircuitBreaker入手
我們是通過(guò)在啟動(dòng)類(lèi)添加@EnableCircuitBreaker注解啟用Hystrix的,所以,源碼解析也要從這個(gè)注解入手。
該注解已經(jīng)被標(biāo)了@Deprecated了,不過(guò),擋不住......
Spring關(guān)于@Enablexxxx注解的套路:通過(guò)@Import注解引入了EnableCircuitBreakerImportSelector.class:
@Deprecated @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(EnableCircuitBreakerImportSelector.class) public @interface EnableCircuitBreaker { }
跟蹤EnableCircuitBreakerImportSelector,繼承自SpringFactoryImportSelector<EnableCircuitBreaker>,注意SpringFactoryImportSelector類(lèi)的泛型類(lèi)型為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); } }
看一下類(lèi)圖:
屬性annotationClass通過(guò)GenericTypeResolver.resolveTypeArgument方法獲取當(dāng)前對(duì)象的泛型參數(shù)的具體類(lèi)型,現(xiàn)在我們知道是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注解我們前面做過(guò)詳細(xì)分析了,實(shí)現(xiàn)了DeferredImportSelector接口表示延遲加載全限定名稱(chēng)為selectImports方法返回的類(lèi)??磗electImports方法:
@Override public String[] selectImports(AnnotationMetadata metadata) { //Enable參數(shù)沒(méi)有打開(kāi)的話(huà)就不加載 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機(jī)制調(diào)用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方法的主要功能就是調(diào)用SpringFactoriesLoader.loadFactoryNames方法,該方法的目的是通過(guò)SPI機(jī)制讀取spring.factories文件中的org.springframework.cloud.client.circuitbreaker相關(guān)配置,返回。
返回的信息是類(lèi)全限定名,從selectImports方法作用可知,這些類(lèi)會(huì)加載到Spring Ioc容器中。
org.springframework.cloud.client.circuitbreaker在spring-cloud-netflix-hystrix-2.2.10.RELEASE包下:
所以該配置下的org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration會(huì)被調(diào)用并加載到Spring IoC容器中。
HystrixCircuitBreakerConfiguration
跟蹤配置類(lèi)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(); }
注入了一個(gè)叫HystrixCommandAspect 的bean,從名字上看,應(yīng)該是關(guān)于HystrixCommand的切面,用到了AOP。其實(shí)也容易理解,加了@HystrixCommand注解的方法的執(zhí)行邏輯發(fā)生了變化:方法增強(qiáng)了執(zhí)行時(shí)長(zhǎng)是否超時(shí)、執(zhí)行是否成功(是否返回異常)、超時(shí)或異常的情況下調(diào)用fallback......方法功能的增強(qiáng)正是AOP的強(qiáng)項(xiàng)。
繼續(xù)跟蹤HystrixCommandAspect 類(lèi)。
HystrixCommandAspect
打開(kāi)代碼,首先是非常熟悉的@Aspect注解:
@Aspect public class HystrixCommandAspect {
表明當(dāng)前類(lèi)是AOP的切面。
繼續(xù)看代碼:
@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 {
添加了針對(duì)注解HystrixCommand的切點(diǎn),以及針對(duì)該切點(diǎn)的環(huán)繞增強(qiáng)方法methodsAnnotatedWithHystrixCommand。
最終的熔斷、限流、服務(wù)降級(jí)功能,都是在這個(gè)methodsAnnotatedWithHystrixCommand方法里實(shí)現(xiàn)的,繼續(xù)向下研究這個(gè)方法的代碼邏輯,需要RxJava背景知識(shí)做支撐。
以上就是Spring cloud Hystrix注解初始化源碼過(guò)程解讀的詳細(xì)內(nèi)容,更多關(guān)于Spring cloud Hystrix注解初始化的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
如何把spring boot應(yīng)用發(fā)布到Harbor
這篇文章主要介紹了如何把spring boot應(yīng)用發(fā)布到Harbor,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11Java實(shí)現(xiàn)局域網(wǎng)聊天室功能(私聊、群聊)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)局域網(wǎng)聊天室功能,包括私聊、群聊,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05SWT(JFace)體驗(yàn)之StackLayout布局
SWT(JFace)體驗(yàn)之StackLayout布局實(shí)現(xiàn)代碼。2009-06-06java8使用filter()取出自己所需數(shù)據(jù)
這篇文章主要介紹了java8使用filter()取出自己所需數(shù)據(jù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05Java實(shí)現(xiàn)布隆過(guò)濾器的方法步驟
布隆過(guò)濾器是可以用于判斷一個(gè)元素是不是在一個(gè)集合里,并且相比于其它的數(shù)據(jù)結(jié)構(gòu),布隆過(guò)濾器在空間和時(shí)間方面都有巨大的優(yōu)勢(shì)。下面這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)布隆過(guò)濾器的相關(guān)資料,需要的朋友可以參考下2018-11-11IntelliJ IDEA優(yōu)化配置的實(shí)現(xiàn)
這篇文章主要介紹了IntelliJ IDEA優(yōu)化配置的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07