Spring?cloud?Hystrix注解初始化源碼過程解讀
從@EnableCircuitBreaker入手
我們是通過在啟動(dòng)類添加@EnableCircuitBreaker注解啟用Hystrix的,所以,源碼解析也要從這個(gè)注解入手。
該注解已經(jīng)被標(biāo)了@Deprecated了,不過,擋不住......
Spring關(guān)于@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方法獲取當(dāng)前對(duì)象的泛型參數(shù)的具體類型,現(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注解我們前面做過詳細(xì)分析了,實(shí)現(xiàn)了DeferredImportSelector接口表示延遲加載全限定名稱為selectImports方法返回的類。看selectImports方法:
@Override
public String[] selectImports(AnnotationMetadata metadata) {
//Enable參數(shù)沒有打開的話就不加載
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方法,該方法的目的是通過SPI機(jī)制讀取spring.factories文件中的org.springframework.cloud.client.circuitbreaker相關(guān)配置,返回。
返回的信息是類全限定名,從selectImports方法作用可知,這些類會(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
跟蹤配置類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 類。
HystrixCommandAspect
打開代碼,首先是非常熟悉的@Aspect注解:
@Aspect
public class HystrixCommandAspect {表明當(dāng)前類是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注解初始化源碼過程解讀的詳細(xì)內(nèi)容,更多關(guān)于Spring cloud Hystrix注解初始化的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
struts2+jsp+jquery+Jcrop實(shí)現(xiàn)圖片裁剪并上傳實(shí)例
本篇文章主要介紹了struts2+jsp+jquery+Jcrop實(shí)現(xiàn)圖片裁剪并上傳實(shí)例,具有一定的參考價(jià)值,有興趣的可以了解一下。2017-01-01
Java實(shí)現(xiàn)一個(gè)達(dá)達(dá)租車系統(tǒng)的步驟詳解
這篇文章主要給大家介紹了利用Java實(shí)現(xiàn)一個(gè)達(dá)達(dá)租車系統(tǒng)的步驟,文中給出了詳細(xì)的實(shí)現(xiàn)思路和示例代碼,并在文末給出了完整的源碼供大家學(xué)習(xí)下載,需要的朋友可以參考借鑒,下面來一起看看吧。2017-04-04
在本地用idea連接虛擬機(jī)上的hbase集群的實(shí)現(xiàn)代碼
這篇文章主要介紹了在本地用idea連接虛擬機(jī)上的hbase集群的實(shí)現(xiàn)代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10
@WebFilter在SpringBoot無效的原因分析和解決方案
使用Ruoyi的demo部署成功后,發(fā)現(xiàn)js、css等靜態(tài)文件都進(jìn)入了過濾器,但是發(fā)現(xiàn)靜態(tài)文件沒有使用瀏覽器緩存,新建BrowserCacheFilter.java并增加@WebFilter處理,應(yīng)用自動(dòng)重啟后發(fā)現(xiàn)@WebFilter無效,所以本文給大家介紹了@WebFilter在SpringBoot無效的原因分析和解決方案2024-03-03
Dwr3.0純注解(純Java Code配置)配置與應(yīng)用淺析二之前端調(diào)用后端
我們講到了后端純Java Code的Dwr3配置,完全去掉了dwr.xml配置文件,但是對(duì)于使用注解的類卻沒有使用包掃描,而是在Servlet初始化參數(shù)的classes里面加入了我們的Service組件的聲明暴露,對(duì)于這個(gè)問題需要后面我們?cè)偌?xì)細(xì)研究下這篇文章,主要分析介紹前端怎么直接調(diào)用后端2016-04-04
win11?idea?shift+F6快捷鍵失效問題解決方案
這篇文章主要介紹了win11?idea?shift+F6快捷鍵失效問題,本文給大家分享最新解決方案,需要的朋友可以參考下2023-08-08

