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生成新代理对象