之前创建feign代理对象,是偷懒的抄源码中的构建beanDefinition的方式,后面通过spring本身通过beanDefinition去创建bean对象的。
这里面有很多不满足的地方,比如我们的项目pom中引入了uc包,但是上传jar包的过程中上传了同样的uc包,但是getBean出来的是我们项目中的uc包中的对象,这显然是不合理的,源码中是从缓存map中拿的,项目启动的时候就加载好了,而覆盖的话,肯定会影响项目中原有的功能。
根本原因就是,两个不同的uc包数据存放在了一起,改一个另一个也会跟着动,所以要分开存储。
加载jar包的过程,加载jar包中的类到自定义的map< 类的全路径,类本身>中,如果解析到类上面有feignClient注解,那么会自己通过源码包中的Feign.Builder去自己构建代理对象。
1.里面需要client对象,我是从spring原有的feignBuilder中获取的。
2.里面还要添加deCoder,用来解析接口返回的结果的。通过debug发现,feign使用的是OptionalDecoder,抄源码把他拿过来。
3. 调用方有的方法需要token的,这边builder也支持添加拦截器。在拦截器中获取request,添加header属性。
@Autowired
private Feign.Builder feignBuilder; // spring容器本身就有的
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters; // spring容器本身就有的
public Decoder feignDecoder() {
return new OptionalDecoder(
new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)));
}
public Object getFeignProxy(Class clazz,String name,String url){
Target.HardCodedTarget target = new Target.HardCodedTarget(clazz, name, url);
builder.decoder(feignDecoder());
Field clientField = feignBuilder.getClass().getDeclaredFields()[0];
clientField.setAccessible(true);
try {
builder.client((Client) clientField.get(feignBuilder));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
builder.requestInterceptor(feignInterceptor);
Feign feign = builder.build();
Object proxy = null;
try {
proxy = feign.newInstance(target);
} catch (Throwable e) {
log.error("创建feign的代理对象失败",e);
}
// 将代理对象存储进map中
feignJarClazzMap.put(clazz.getName(),proxy);
return proxy;
}
总结:
- 源码中的设计模式还是挺多的,看人家代码,看懂了设计模式,里面的边边角角理解起来就很快了。多去看看优秀的代码,理解里面用到的设计模式。
- java基础还有待提升,Feign本身是个抽象类,但是里面有个内部的静态类Builder,你想要Buuilder,可以直接new。不需要想法设法的去创建Feign然后去构建builder。
- 多思考,多做有效的输出总结。
- 在调用源码中的方法的时候,入口真的很多,无法下手的,还是要自己多看看,那种焦灼的心情,眼前一团乱麻的感觉不好受的
- 有的时候问题本身不是问题,由其他原因引起的。