多平台统一管理软件接口,如何实现多平台统一管理软件接口
433
2022-12-25
spring cloud openfeign 源码实例解析
一、读取注解信息
入口
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class CjsPriceServiceApplication {
public static void main(String[] args) {
SpringApplication.run(CjsPriceServiceApplication.class, args);
}
}
spring boot 项目启动后会自动扫描application上面的注解,@EnableFeignClients的注解如下
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {
。。。。
}
在注解中导入了 FeignClientsRegistrar类,用来像spring注册,EnableFeignClients和FeignClient上面开发人员添加的注解信息
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
registerDefaultConfiguration(metadata, registry);
registerFeignClients(metadata, registry);
}
二、当项目启动,读取@Autowired时会调用,实现了FactoryBean接口的FeignClientFactoryBean.getObject()方法
@Override
public Object getObject() throws Exception {
return getTarget();
}
FeignContext context = this.applicationContext.getBean(FeignContext.class);
Feign.Builder builder = feign(context);
if (!StringUtils.hasText(this.url)) {
if (!this.name.startsWith("http")) {
this.url = "http://" + this.name;
}
else {
this.url = this.name;
}
this.url += cleanPath();
return (T) loadBalance(builder, context,
new HardCodedTarget<>(this.type, this.name, this.url));
}
if (StringUtils.hasText(this.url) && !this.url.startsWith("http")) {
this.url = "http://" + this.url;
}
String url = this.url + cleanPath();
Client client = getOptional(context, Client.class);
if (client != null) {
if (client instanceof LoadBalancerFeignClient) {
// not load balancing because we have a url,
// but ribbon is on the classpath, so unwrap
client = ((LoadBalancerFeignClient) client).getDelegate();
}
builder.client(client);
}
Targeter targeter = get(context, Targeter.class);
return (T) targeter.target(this, builder, context,
new HardCodedTarget<>(this.type, this.name, url));
}
可以看到 getTarget()有两种返回结果的情况,其原理都一样后来调用了 targeter.target()方法
package org.springframework.cloud.openfeign;
import feign.Feign;
import feign.Target;
/**
* @author Spencer Gibb
*/
interface Targeter {
FeignContext context, Target.HardCodedTarget
}
默认实现类
package org.springframework.cloud.openfeign;
import feign.Feign;
import feign.Target;
/**
* @author Spencer Gibb
*/
class DefaultTargeter implements Targeter {
@Override
public
FeignContext context, Target.HardCodedTarget
return feign.target(target);
}
}
然后再看 feign.target(target);方法
public
return build().newInstance(target);
}
public Feign build() {
SynchronousMethodHandler.Factory synchronousMethodHandlerFactory =
new SynchronousMethodHandler.Factory(client, retryer, requestInterceptors, logger,
logLevel, decode404, closeAfterDecode, propagationPolicy);
ParseHandlersByName handlersByName =
new ParseHandlersByName(contract, options, encoder, decoder, queryMapEncoder,
errorDecoder, synchronousMethodHandlerFactory);
return new ReflectiveFeign(handlersByName, invocationHandlerFacthttp://ory, queryMapEncoder);
}
}
build()方法返回了创建代理类的对象,然后调用了创建代理的 newInstance方法
public
Map
Map
List
for (Method method : target.type().getMethods()) {
if (method.getDeclaringClass() == Object.class) {
continue;
} 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);
T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(),
new Class>[] {target.type()}, handler);
http:// for (DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {
defaultMethodHandler.bindTo(proxy);
}
return proxy;
}
最后,当我们项目中使用 @Autowired注入时,就回调用工厂类 FeignClientFactoryBean方法的 getObject()方法 返回我们的代理对象
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~