Spring-Cloud-OpenFeign源码解析-03-FeignClientFactoryBean

Spring-Cloud-OpenFeign源码解析-02-OpenFeign自动装配分析到OpenFeign 接口代理对象的创建是通过构建成一个 FeignClientFactoryBean 对象,并最后注入到容器中的,那么这个FeignClientFactoryBean是如何实现代理对象创建的呢?

FactoryBean

public interface FactoryBean<T> {
    
	String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
    
	@Nullable
	T getObject() throws Exception;

	@Nullable
	Class<?> getObjectType();
    
	default boolean isSingleton() {
		return true;
	}

FactoryBean是Spring框架中的一个扩展接口,用于创建和管理其他Bean实例的对象。使用它可以生成某些需要复杂初始化过程的bean对象。当配置某个bean实现了FactoryBean接口时,该bean返回的对象不是FactoryBean本身,而是FactoryBean#getObject()方法返回的对象,这就提供了我们自定义创建对象的能力。

它与Spring其他bean的主要区别在于,FactoryBean负责产生其他bean实例。也即当我们从IOC容器中获取一个FactoryBean时,我们得到的是它创建的那个bean的实例,而不是FactoryBean的实例本身。

FeignClientFactoryBean
public class FeignClientFactoryBean
		implements FactoryBean<Object>, InitializingBean, ApplicationContextAware, BeanFactoryAware {
    
        @Override
        public Object getObject() {
            //调用getTarget()方法
            return getTarget();
        }
    
		/**
	 	* @param <T> the target type of the Feign client
	 	* @return a {@link Feign} client created with the specified data and the context
	 	* information
	 	*/
    	<T> T getTarget() {
		FeignContext context = beanFactory != null ? beanFactory.getBean(FeignContext.class)
				: applicationContext.getBean(FeignContext.class);
		Feign.Builder builder = feign(context);
		// 判断当前FeignClient注解中的url是否为空,如果不为空,直接通过url的调用
		if (!StringUtils.hasText(url)) {
			if (LOG.isInfoEnabled()) {
				LOG.info("For '" + name + "' URL not provided. Will try picking an instance via load-balancing.");
			}
             //是否以http开头
			if (!name.startsWith("http")) {
				url = "http://" + name;
			}
			else {
				url = name;
			}
			url += cleanPath();
             //返回目标对象
			return (T) loadBalance(builder, context, new HardCodedTarget<>(type, name, url));
		}
		if (StringUtils.hasText(url) && !url.startsWith("http")) {
			url = "http://" + url;
		}
		String url = this.url + cleanPath();
		Client client = getOptional(context, Client.class);
		if (client != null) {
			if (client instanceof FeignBlockingLoadBalancerClient) {
				// not load balancing because we have a url,
				// but Spring Cloud LoadBalancer is on the classpath, so unwrap
				client = ((FeignBlockingLoadBalancerClient) client).getDelegate();
			}
			if (client instanceof RetryableFeignBlockingLoadBalancerClient) {
				// not load balancing because we have a url,
				// but Spring Cloud LoadBalancer is on the classpath, so unwrap
				client = ((RetryableFeignBlockingLoadBalancerClient) client).getDelegate();
			}
			builder.client(client);
		}

		applyBuildCustomizers(context, builder);

		Targeter targeter = get(context, Targeter.class);
         //返回目标对象
		return (T) targeter.target(this, builder, context, new HardCodedTarget<>(type, name, url));
	}
}


	protected <T> T loadBalance(Feign.Builder builder, FeignContext context, HardCodedTarget<T> target) {
		Client client = getOptional(context, Client.class);
		if (client != null) {
			builder.client(client);
			applyBuildCustomizers(context, builder);
			Targeter targeter = get(context, Targeter.class);
             //返回目标对象
			return targeter.target(this, builder, context, target);
		}

		throw new IllegalStateException(
				"No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalancer?");
	}

最终都会调用到targeter.target()方法

Targeter#target()

默认调用的是DefaultTargeter

class DefaultTargeter implements Targeter {

	@Override
	public <T> T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context,
			Target.HardCodedTarget<T> target) {
         //继续调用target方法
		return feign.target(target);
	}
}

feign.target()

public abstract class Feign {
	
    public <T> T target(Target<T> target) {
      //创建代理对象
      return build().newInstance(target);
    }
    
    //构建Feign对象
    public Feign build() {
      Client client = Capability.enrich(this.client, capabilities);
      Retryer retryer = Capability.enrich(this.retryer, capabilities);
      List<RequestInterceptor> requestInterceptors = this.requestInterceptors.stream()
          .map(ri -> Capability.enrich(ri, capabilities))
          .collect(Collectors.toList());
      Logger logger = Capability.enrich(this.logger, capabilities);
      Contract contract = Capability.enrich(this.contract, capabilities);
      Options options = Capability.enrich(this.options, capabilities);
      Encoder encoder = Capability.enrich(this.encoder, capabilities);
      Decoder decoder = Capability.enrich(this.decoder, capabilities);
      //创建代理对象的InvocationHandler工厂实例
      InvocationHandlerFactory invocationHandlerFactory =
          Capability.enrich(this.invocationHandlerFactory, capabilities);
      QueryMapEncoder queryMapEncoder = Capability.enrich(this.queryMapEncoder, capabilities);

      SynchronousMethodHandler.Factory synchronousMethodHandlerFactory =
          new SynchronousMethodHandler.Factory(client, retryer, requestInterceptors, logger,
              logLevel, decode404, closeAfterDecode, propagationPolicy, forceDecoding);
      ParseHandlersByName handlersByName =
          new ParseHandlersByName(contract, options, encoder, decoder, queryMapEncoder,
              errorDecoder, synchronousMethodHandlerFactory);
      //最终返回ReflectiveFeign实例
      return new ReflectiveFeign(handlersByName, invocationHandlerFactory, queryMapEncoder);
    }
}

ReflectiveFeign.newInstance()

public class ReflectiveFeign extends Feign {
	
  @Override
  public <T> T newInstance(Target<T> target) {
    Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);
    Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>();
    List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList<DefaultMethodHandler>();
	//解析方法,封装为MethodHandler
    for (Method method : target.type().getMethods()) {
      //Object方法
      if (method.getDeclaringClass() == Object.class) {
        continue;
        //Default方法
      } else if (Util.isDefault(method)) {
        DefaultMethodHandler handler = new DefaultMethodHandler(method);
        defaultMethodHandlers.add(handler);
        methodToHandler.put(method, handler);
      } else {
        methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
      }
    }
    InvocationHandler handler = factory.create(target, methodToHandler);
    //jdk动态代理创建对象
    T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(),
        new Class<?>[] {target.type()}, handler);

    for (DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {
      defaultMethodHandler.bindTo(proxy);
    }
    //返回代理对象
    return proxy;
  }
}

总结

通过创建FeignClientFactoryBean对象,在@Autowired或者@Resource注入FeignClient实例的时候,实际上返回的是FactoryBean#getObject()方法创建的对象,底层通过JDK动态代理Proxy.newProxyInstance()返回代理对象,具体的实现逻辑在InvocationHandler的invoke方法中

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值