1、样例
/**
* http://127.0.0.1:8080/user/hello
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserClient userClient;
@RequestMapping("/hello")
public String hello() {
return userClient.sayHello();
}
}
import home.spring.cloud.Hystrix.UserClientFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient(value = "user", fallback = UserClientFallback.class)
public interface UserClient {
@RequestMapping("/users/222")
String sayHello();
}
import home.spring.cloud.Feign.UserClient;
import org.springframework.stereotype.Component;
@Component
public class UserClientFallback implements UserClient {
@Override
public String sayHello() {
return "Oh! Error!!!";
}
}
当UserController.hello中,去调用userClient接口方法时,其实调用的是一个代理类,代理类如下
feign.hystrix.HystrixInvocationHandler#invoke 下面是该方法的主要逻辑
HystrixCommand<Object> hystrixCommand = new HystrixCommand<Object>(setterMethodMap.get(method)) {
@Override
protected Object run() throws Exception {
try {
return HystrixInvocationHandler.this.dispatch.get(method).invoke(args);
} catch (Exception e) {
throw e;
} catch (Throwable t) {
throw (Error) t;
}
}
@Override
protected Object getFallback() {
if (fallbackFactory == null) {
return super.getFallback();
}
try {
Object fallback = fallbackFactory.create(getExecutionException());
Object result = fallbackMethodMap.get(method).invoke(fallback, args);
if (isReturnsHystrixCommand(method)) {
return ((HystrixCommand) result).execute();
} else if (isReturnsObservable(method)) {
// Create a cold Observable
return ((Observable) result).toBlocking().first();
} else if (isReturnsSingle(method)) {
// Create a cold Observable as a Single
return ((Single) result).toObservable().toBlocking().first();
} else if (isReturnsCompletable(method)) {
((Completable) result).await();
return null;
} else {
return result;
}
} catch (IllegalAccessException e) {
// shouldn't happen as method is public due to being an interface
throw new AssertionError(e);
} catch (InvocationTargetException e) {
// Exceptions on fallback are tossed by Hystrix
throw new AssertionError(e.getCause());
}
}
};
if (isReturnsHystrixCommand(method)) {
return hystrixCommand;
} else if (isReturnsObservable(method)) {
// Create a cold Observable
return hystrixCommand.toObservable();
} else if (isReturnsSingle(method)) {
// Create a cold Observable as a Single
return hystrixCommand.toObservable().toSingle();
} else if (isReturnsCompletable(method)) {
return hystrixCommand.toObservable().toCompletable();
}
return hystrixCommand.execute();
}
一目了然,直接新建一个HystrixCommand对象,进行调用实际的rpc接口
HystrixInvocationHandler 这类对象什么时候创建的?
首先要加注解 @EnableFeignClients
启动的时候,spring初始化beanDefined对象(UserClient userClient)时候,reflush() 中间有一个步骤
invokeBeanFactoryPostProcessors(beanFactory) 上述的handler代理类是通过Factory生成的
步骤调用了org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions
经过org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>)
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
这个方法里面解析了注解@Import
这样就直接调用到了
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {
class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar,
ResourceLoaderAware, EnvironmentAware {
// patterned after Spring Integration IntegrationComponentScanRegistrar
// and RibbonClientsConfigurationRegistgrar
private ResourceLoader resourceLoader;
private Environment environment;
public FeignClientsRegistrar() {
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, // 直接调用此方法注册一些代理类
BeanDefinitionRegistry registry) {
registerDefaultConfiguration(metadata, registry);
registerFeignClients(metadata, registry);
}
private void registerDefaultConfiguration(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
Map<String, Object> defaultAttrs = metadata
.getAnnotationAttributes(EnableFeignClients.class.getName(), true);
if (defaultAttrs != null && defaultAttrs.containsKey("defaultConfiguration")) {
直接生成
FeignClientFactoryBean getObject生成新代理对象
本文详细解析了Feign与Hystrix在Spring Cloud框架中的集成原理,展示了如何通过代理类实现RPC调用及故障容错机制。深入探讨了HystrixCommand对象的创建过程,以及FeignClientsRegistrar在Bean定义注册中的作用。
167万+

被折叠的 条评论
为什么被折叠?



